merge the formfield patch from ooo-build
[ooovba.git] / sc / source / filter / excel / xestyle.cxx
blobde32a64960fb57a42adfabfbe6f1c9a70bd645c8
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: xestyle.cxx,v $
10 * $Revision: 1.33.32.3 $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_sc.hxx"
33 #include "xestyle.hxx"
35 #include <algorithm>
36 #include <iterator>
37 #include <set>
38 #include <com/sun/star/i18n/ScriptType.hpp>
39 #include <vcl/font.hxx>
40 #include <svtools/zformat.hxx>
41 #include <svtools/languageoptions.hxx>
42 #include <sfx2/printer.hxx>
43 #include "scitems.hxx"
44 #include <svx/algitem.hxx>
45 #include <svx/boxitem.hxx>
46 #include <svx/bolnitem.hxx>
47 #include <svx/rotmodit.hxx>
48 #include <svx/colritem.hxx>
49 #include <svx/brshitem.hxx>
50 #include <svx/frmdiritem.hxx>
51 #include <svx/eeitem.hxx>
52 #include <svx/escpitem.hxx>
53 #include "document.hxx"
54 #include "stlpool.hxx"
55 #include "stlsheet.hxx"
56 #include "patattr.hxx"
57 #include "attrib.hxx"
58 #include "globstr.hrc"
59 #include "xestring.hxx"
61 #include <oox/core/tokens.hxx>
63 using ::rtl::OString;
64 using ::rtl::OUString;
66 // PALETTE record - color information =========================================
68 namespace {
70 sal_uInt32 lclGetWeighting( XclExpColorType eType )
72 switch( eType )
74 case EXC_COLOR_CHARTLINE: return 1;
75 case EXC_COLOR_CELLBORDER:
76 case EXC_COLOR_CHARTAREA: return 2;
77 case EXC_COLOR_CELLTEXT:
78 case EXC_COLOR_CHARTTEXT:
79 case EXC_COLOR_CTRLTEXT: return 10;
80 case EXC_COLOR_TABBG:
81 case EXC_COLOR_CELLAREA: return 20;
82 case EXC_COLOR_GRID: return 50;
83 default: DBG_ERRORFILE( "lclGetWeighting - unknown color type" );
85 return 1;
88 sal_Int32 lclGetColorDistance( const Color& rColor1, const Color& rColor2 )
90 sal_Int32 nDist = rColor1.GetRed() - rColor2.GetRed();
91 nDist *= nDist * 77;
92 sal_Int32 nDummy = rColor1.GetGreen() - rColor2.GetGreen();
93 nDist += nDummy * nDummy * 151;
94 nDummy = rColor1.GetBlue() - rColor2.GetBlue();
95 nDist += nDummy * nDummy * 28;
96 return nDist;
99 sal_uInt8 lclGetMergedColorComp( sal_uInt8 nComp1, sal_uInt32 nWeight1, sal_uInt8 nComp2, sal_uInt32 nWeight2 )
101 sal_uInt8 nComp1Dist = ::std::min< sal_uInt8 >( nComp1, 0xFF - nComp1 );
102 sal_uInt8 nComp2Dist = ::std::min< sal_uInt8 >( nComp2, 0xFF - nComp2 );
103 if( nComp1Dist != nComp2Dist )
105 /* #i36945# One of the passed RGB components is nearer at the limits (0x00 or 0xFF).
106 Increase its weighting to prevent fading of the colors during reduction. */
107 const sal_uInt8& rnCompNearer = (nComp1Dist < nComp2Dist) ? nComp1 : nComp2;
108 sal_uInt32& rnWeight = (nComp1Dist < nComp2Dist) ? nWeight1 : nWeight2;
109 rnWeight *= ((rnCompNearer - 0x80L) * (rnCompNearer - 0x7FL) / 0x1000L + 1);
111 sal_uInt32 nWSum = nWeight1 + nWeight2;
112 return static_cast< sal_uInt8 >( (nComp1 * nWeight1 + nComp2 * nWeight2 + nWSum / 2) / nWSum );
115 void lclSetMixedColor( Color& rDest, const Color& rSrc1, const Color& rSrc2 )
117 rDest.SetRed( static_cast< sal_uInt8 >( (static_cast< sal_uInt16 >( rSrc1.GetRed() ) + rSrc2.GetRed()) / 2 ) );
118 rDest.SetGreen( static_cast< sal_uInt8 >( (static_cast< sal_uInt16 >( rSrc1.GetGreen() ) + rSrc2.GetGreen()) / 2 ) );
119 rDest.SetBlue( static_cast< sal_uInt8 >( (static_cast< sal_uInt16 >( rSrc1.GetBlue() ) + rSrc2.GetBlue()) / 2 ) );
122 } // namespace
124 // additional classes for color reduction -------------------------------------
126 namespace {
128 /** Represents an entry in a color list.
130 The color stores a weighting value, which increases the more the color is
131 used in the document. Heavy-weighted colors will change less than others on
132 color reduction.
134 class XclListColor
136 DECL_FIXEDMEMPOOL_NEWDEL( XclListColor )
138 private:
139 Color maColor; /// The color value of this palette entry.
140 sal_uInt32 mnColorId; /// Unique color ID for color reduction.
141 sal_uInt32 mnWeight; /// Weighting for color reduction.
142 bool mbBaseColor; /// true = Handle as base color, (don't remove/merge).
144 public:
145 explicit XclListColor( const Color& rColor, sal_uInt32 nColorId );
147 /** Returns the RGB color value of the color. */
148 inline const Color& GetColor() const { return maColor; }
149 /** Returns the unique ID of the color. */
150 inline sal_uInt32 GetColorId() const { return mnColorId; }
151 /** Returns the current weighting of the color. */
152 inline sal_uInt32 GetWeighting() const { return mnWeight; }
153 /** Returns true, if this color is a base color, i.e. it will not be removed or merged. */
154 inline bool IsBaseColor() const { return mbBaseColor; }
156 /** Adds the passed weighting to this color. */
157 inline void AddWeighting( sal_uInt32 nWeight ) { mnWeight += nWeight; }
158 /** Merges this color with rColor, regarding weighting settings. */
159 void Merge( const XclListColor& rColor );
162 IMPL_FIXEDMEMPOOL_NEWDEL( XclListColor, 100, 100 )
164 XclListColor::XclListColor( const Color& rColor, sal_uInt32 nColorId ) :
165 maColor( rColor ),
166 mnColorId( nColorId ),
167 mnWeight( 0 )
169 mbBaseColor =
170 ((rColor.GetRed() == 0x00) || (rColor.GetRed() == 0xFF)) &&
171 ((rColor.GetGreen() == 0x00) || (rColor.GetGreen() == 0xFF)) &&
172 ((rColor.GetBlue() == 0x00) || (rColor.GetBlue() == 0xFF));
175 void XclListColor::Merge( const XclListColor& rColor )
177 sal_uInt32 nWeight2 = rColor.GetWeighting();
178 // do not change RGB value of base colors
179 if( !mbBaseColor )
181 maColor.SetRed( lclGetMergedColorComp( maColor.GetRed(), mnWeight, rColor.maColor.GetRed(), nWeight2 ) );
182 maColor.SetGreen( lclGetMergedColorComp( maColor.GetGreen(), mnWeight, rColor.maColor.GetGreen(), nWeight2 ) );
183 maColor.SetBlue( lclGetMergedColorComp( maColor.GetBlue(), mnWeight, rColor.maColor.GetBlue(), nWeight2 ) );
185 AddWeighting( nWeight2 );
188 // ----------------------------------------------------------------------------
190 /** Data for each inserted original color, represented by a color ID. */
191 struct XclColorIdData
193 Color maColor; /// The original inserted color.
194 sal_uInt32 mnIndex; /// Maps current color ID to color list or export color vector.
195 /** Sets the contents of this struct. */
196 inline void Set( const Color& rColor, sal_uInt32 nIndex ) { maColor = rColor; mnIndex = nIndex; }
199 /** A color that will be written to the Excel file. */
200 struct XclPaletteColor
202 Color maColor; /// Resulting color to export.
203 bool mbUsed; /// true = Entry is used in the document.
205 inline explicit XclPaletteColor( const Color& rColor ) : maColor( rColor ), mbUsed( false ) {}
206 inline void SetColor( const Color& rColor ) { maColor = rColor; mbUsed = true; }
209 /** Maps a color list index to a palette index.
210 @descr Used to remap the color ID data vector from list indexes to palette indexes. */
211 struct XclRemap
213 sal_uInt32 mnPalIndex; /// Index to palette.
214 bool mbProcessed; /// true = List color already processed.
216 inline explicit XclRemap() : mnPalIndex( 0 ), mbProcessed( false ) {}
217 inline void SetIndex( sal_uInt32 nPalIndex )
218 { mnPalIndex = nPalIndex; mbProcessed = true; }
221 /** Stores the nearest palette color index of a list color. */
222 struct XclNearest
224 sal_uInt32 mnPalIndex; /// Index to nearest palette color.
225 sal_Int32 mnDist; /// Distance to palette color.
227 inline explicit XclNearest() : mnPalIndex( 0 ), mnDist( 0 ) {}
230 typedef ::std::vector< XclRemap > XclRemapVec;
231 typedef ::std::vector< XclNearest > XclNearestVec;
233 } // namespace
235 // ----------------------------------------------------------------------------
237 class XclExpPaletteImpl
239 public:
240 explicit XclExpPaletteImpl( const XclDefaultPalette& rDefPal );
242 /** Inserts the color into the list and updates weighting.
243 @param nAutoDefault The Excel palette index for automatic color.
244 @return A unique ID for this color. */
245 sal_uInt32 InsertColor( const Color& rColor, XclExpColorType eType, sal_uInt16 nAutoDefault = 0 );
246 /** Returns the color ID representing a fixed Excel palette index (i.e. for auto colors). */
247 static sal_uInt32 GetColorIdFromIndex( sal_uInt16 nIndex );
249 /** Reduces the color list to the maximum count of the current BIFF version. */
250 void Finalize();
252 /** Returns the Excel palette index of the color with passed color ID. */
253 sal_uInt16 GetColorIndex( sal_uInt32 nColorId ) const;
255 /** Returns a foreground and background color for the two passed color IDs.
256 @descr If rnXclPattern contains a solid pattern, this function tries to find
257 the two best fitting colors and a mix pattern (25%, 50% or 75%) for nForeColorId.
258 This will result in a better approximation to the passed foreground color. */
259 void GetMixedColors(
260 sal_uInt16& rnXclForeIx, sal_uInt16& rnXclBackIx, sal_uInt8& rnXclPattern,
261 sal_uInt32 nForeColorId, sal_uInt32 nBackColorId ) const;
263 /** Returns the RGB color data for a (non-zero-based) Excel palette entry.
264 @return The color from current or default palette or COL_AUTO, if nothing else found. */
265 ColorData GetColorData( sal_uInt16 nXclIndex ) const;
266 /** Returns the color for a (non-zero-based) Excel palette entry.
267 @return The color from current or default palette or COL_AUTO, if nothing else found. */
268 inline Color GetColor( sal_uInt16 nXclIndex ) const
269 { return Color( GetColorData( nXclIndex ) ); }
271 /** Returns true, if all colors of the palette are equal to default palette colors. */
272 bool IsDefaultPalette() const;
273 /** Writes the color list (contents of the palette record) to the passed stream. */
274 void WriteBody( XclExpStream& rStrm );
275 void SaveXml( XclExpXmlStream& rStrm );
277 private:
278 /** Returns the Excel index of a 0-based color index. */
279 inline sal_uInt16 GetXclIndex( sal_uInt32 nIndex ) const
280 { return static_cast< sal_uInt16 >( nIndex + EXC_COLOR_USEROFFSET ); }
282 /** Returns the original inserted color represented by the color ID nColorId. */
283 const Color& GetOriginalColor( sal_uInt32 nColorId ) const;
285 /** Searches for rColor, returns the ordered insertion index for rColor in rnIndex. */
286 XclListColor* SearchListEntry( const Color& rColor, sal_uInt32& rnIndex );
287 /** Creates and inserts a new color list entry at the specified list position. */
288 XclListColor* CreateListEntry( const Color& rColor, sal_uInt32 nIndex );
290 /** Raw and fast reduction of the palette. */
291 void RawReducePalette( sal_uInt32 nPass );
292 /** Reduction of one color using advanced color merging based on color weighting. */
293 void ReduceLeastUsedColor();
295 /** Finds the least used color and returns its current list index. */
296 sal_uInt32 GetLeastUsedListColor() const;
297 /** Returns the list index of the color nearest to rColor.
298 @param nIgnore List index of a color which will be ignored.
299 @return The list index of the found color. */
300 sal_uInt32 GetNearestListColor( const Color& rColor, sal_uInt32 nIgnore ) const;
301 /** Returns the list index of the color nearest to the color with list index nIndex. */
302 sal_uInt32 GetNearestListColor( sal_uInt32 nIndex ) const;
304 /** Returns in rnIndex the palette index of the color nearest to rColor.
305 @param bDefaultOnly true = Searches for default colors only (colors never replaced).
306 @return The distance from passed color to found color. */
307 sal_Int32 GetNearestPaletteColor(
308 sal_uInt32& rnIndex,
309 const Color& rColor, bool bDefaultOnly ) const;
310 /** Returns in rnFirst and rnSecond the palette indexes of the two colors nearest to rColor.
311 @return The minimum distance from passed color to found colors. */
312 sal_Int32 GetNearPaletteColors(
313 sal_uInt32& rnFirst, sal_uInt32& rnSecond,
314 const Color& rColor ) const;
316 private:
317 typedef ScfDelList< XclListColor > XclListColorList;
318 typedef ScfRef< XclListColorList > XclListColorListRef;
319 typedef ::std::vector< XclColorIdData > XclColorIdDataVec;
320 typedef ::std::vector< XclPaletteColor > XclPaletteColorVec;
322 const XclDefaultPalette& mrDefPal; /// The default palette for the current BIFF version.
323 XclListColorListRef mxColorList; /// Working color list.
324 XclColorIdDataVec maColorIdDataVec; /// Data of all CIDs.
325 XclPaletteColorVec maPalette; /// Contains resulting colors to export.
326 sal_uInt32 mnLastIdx; /// Last insertion index for search opt.
329 // ----------------------------------------------------------------------------
331 const sal_uInt32 EXC_PAL_INDEXBASE = 0xFFFF0000;
332 const sal_uInt32 EXC_PAL_MAXRAWSIZE = 1024;
334 XclExpPaletteImpl::XclExpPaletteImpl( const XclDefaultPalette& rDefPal ) :
335 mrDefPal( rDefPal ),
336 mxColorList( new XclListColorList ),
337 mnLastIdx( 0 )
339 // initialize maPalette with default colors
340 sal_uInt16 nCount = static_cast< sal_uInt16 >( mrDefPal.GetColorCount() );
341 maPalette.reserve( nCount );
342 for( sal_uInt16 nIdx = 0; nIdx < nCount; ++nIdx )
343 maPalette.push_back( XclPaletteColor( mrDefPal.GetDefColor( GetXclIndex( nIdx ) ) ) );
345 InsertColor( Color( COL_BLACK ), EXC_COLOR_CELLTEXT );
348 sal_uInt32 XclExpPaletteImpl::InsertColor( const Color& rColor, XclExpColorType eType, sal_uInt16 nAutoDefault )
350 if( rColor.GetColor() == COL_AUTO )
351 return GetColorIdFromIndex( nAutoDefault );
353 sal_uInt32 nFoundIdx = 0;
354 XclListColor* pEntry = SearchListEntry( rColor, nFoundIdx );
355 if( !pEntry || (pEntry->GetColor() != rColor) )
356 pEntry = CreateListEntry( rColor, nFoundIdx );
357 pEntry->AddWeighting( lclGetWeighting( eType ) );
359 return pEntry->GetColorId();
362 sal_uInt32 XclExpPaletteImpl::GetColorIdFromIndex( sal_uInt16 nIndex )
364 return EXC_PAL_INDEXBASE | nIndex;
367 void XclExpPaletteImpl::Finalize()
369 // --- build initial color ID data vector (maColorIdDataVec) ---
371 sal_uInt32 nCount = mxColorList->Count();
372 maColorIdDataVec.resize( nCount );
373 for( sal_uInt32 nIdx = 0; nIdx < nCount; ++nIdx )
375 XclListColor* pListColor = mxColorList->GetObject( nIdx );
376 maColorIdDataVec[ pListColor->GetColorId() ].Set( pListColor->GetColor(), nIdx );
379 // --- loop as long as current color count does not fit into palette of current BIFF ---
381 // phase 1: raw reduction (performance reasons, #i36945#)
382 sal_uInt32 nPass = 0;
383 while( mxColorList->Count() > EXC_PAL_MAXRAWSIZE )
384 RawReducePalette( nPass++ );
386 // phase 2: precise reduction using advanced color merging based on color weighting
387 while( mxColorList->Count() > mrDefPal.GetColorCount() )
388 ReduceLeastUsedColor();
390 // --- #104865# use default palette and replace colors with nearest used colors ---
392 nCount = mxColorList->Count();
393 XclRemapVec aRemapVec( nCount );
394 XclNearestVec aNearestVec( nCount );
396 // in each run: search the best fitting color and replace a default color with it
397 for( sal_uInt32 nRun = 0; nRun < nCount; ++nRun )
399 sal_uInt32 nIndex;
400 // find nearest unused default color for each unprocessed list color
401 for( nIndex = 0; nIndex < nCount; ++nIndex )
402 aNearestVec[ nIndex ].mnDist = aRemapVec[ nIndex ].mbProcessed ? SAL_MAX_INT32 :
403 GetNearestPaletteColor( aNearestVec[ nIndex ].mnPalIndex, mxColorList->GetObject( nIndex )->GetColor(), true );
404 // find the list color which is nearest to a default color
405 sal_uInt32 nFound = 0;
406 for( nIndex = 1; nIndex < nCount; ++nIndex )
407 if( aNearestVec[ nIndex ].mnDist < aNearestVec[ nFound ].mnDist )
408 nFound = nIndex;
409 // replace default color with list color
410 sal_uInt32 nNearest = aNearestVec[ nFound ].mnPalIndex;
411 DBG_ASSERT( mxColorList->GetObject( nFound ), "XclExpPaletteImpl::Finalize - missing a color" );
412 DBG_ASSERT( nNearest < maPalette.size(), "XclExpPaletteImpl::Finalize - algorithm error" );
413 maPalette[ nNearest ].SetColor( mxColorList->GetObject( nFound )->GetColor() );
414 aRemapVec[ nFound ].SetIndex( nNearest );
417 // remap color ID data map (maColorIdDataVec) from list indexes to palette indexes
418 for( XclColorIdDataVec::iterator aIt = maColorIdDataVec.begin(), aEnd = maColorIdDataVec.end(); aIt != aEnd; ++aIt )
419 aIt->mnIndex = aRemapVec[ aIt->mnIndex ].mnPalIndex;
422 sal_uInt16 XclExpPaletteImpl::GetColorIndex( sal_uInt32 nColorId ) const
424 sal_uInt16 nRet = 0;
425 if( nColorId >= EXC_PAL_INDEXBASE )
426 nRet = static_cast< sal_uInt16 >( nColorId & ~EXC_PAL_INDEXBASE );
427 else if( nColorId < maColorIdDataVec.size() )
428 nRet = GetXclIndex( maColorIdDataVec[ nColorId ].mnIndex );
429 return nRet;
432 void XclExpPaletteImpl::GetMixedColors(
433 sal_uInt16& rnXclForeIx, sal_uInt16& rnXclBackIx, sal_uInt8& rnXclPattern,
434 sal_uInt32 nForeColorId, sal_uInt32 nBackColorId ) const
436 rnXclForeIx = GetColorIndex( nForeColorId );
437 rnXclBackIx = GetColorIndex( nBackColorId );
438 if( (rnXclPattern != EXC_PATT_SOLID) || (nForeColorId >= maColorIdDataVec.size()) )
439 return;
441 // now we have solid pattern, and a defined foreground (background doesn't care for solid pattern)
443 sal_uInt32 nIndex1, nIndex2;
444 Color aForeColor( GetOriginalColor( nForeColorId ) );
445 sal_Int32 nFirstDist = GetNearPaletteColors( nIndex1, nIndex2, aForeColor );
446 if( (nIndex1 >= maPalette.size()) || (nIndex2 >= maPalette.size()) )
447 return;
449 Color aColorArr[ 5 ];
450 aColorArr[ 0 ] = maPalette[ nIndex1 ].maColor;
451 aColorArr[ 4 ] = maPalette[ nIndex2 ].maColor;
452 lclSetMixedColor( aColorArr[ 2 ], aColorArr[ 0 ], aColorArr[ 4 ] );
453 lclSetMixedColor( aColorArr[ 1 ], aColorArr[ 0 ], aColorArr[ 2 ] );
454 lclSetMixedColor( aColorArr[ 3 ], aColorArr[ 2 ], aColorArr[ 4 ] );
456 sal_Int32 nMinDist = nFirstDist;
457 sal_uInt32 nMinIndex = 0;
458 for( sal_uInt32 nCnt = 1; nCnt < 4; ++nCnt )
460 sal_Int32 nDist = lclGetColorDistance( aForeColor, aColorArr[ nCnt ] );
461 if( nDist < nMinDist )
463 nMinDist = nDist;
464 nMinIndex = nCnt;
467 rnXclForeIx = GetXclIndex( nIndex1 );
468 rnXclBackIx = GetXclIndex( nIndex2 );
469 if( nMinDist < nFirstDist )
471 switch( nMinIndex )
473 case 1: rnXclPattern = EXC_PATT_75_PERC; break;
474 case 2: rnXclPattern = EXC_PATT_50_PERC; break;
475 case 3: rnXclPattern = EXC_PATT_25_PERC; break;
480 ColorData XclExpPaletteImpl::GetColorData( sal_uInt16 nXclIndex ) const
482 if( nXclIndex >= EXC_COLOR_USEROFFSET )
484 sal_uInt32 nIdx = nXclIndex - EXC_COLOR_USEROFFSET;
485 if( nIdx < maPalette.size() )
486 return maPalette[ nIdx ].maColor.GetColor();
488 return mrDefPal.GetDefColorData( nXclIndex );
491 bool XclExpPaletteImpl::IsDefaultPalette() const
493 bool bDefault = true;
494 for( sal_uInt32 nIdx = 0, nSize = static_cast< sal_uInt32 >( maPalette.size() ); bDefault && (nIdx < nSize); ++nIdx )
495 bDefault = maPalette[ nIdx ].maColor == mrDefPal.GetDefColor( GetXclIndex( nIdx ) );
496 return bDefault;
499 void XclExpPaletteImpl::WriteBody( XclExpStream& rStrm )
501 rStrm << static_cast< sal_uInt16 >( maPalette.size() );
502 for( XclPaletteColorVec::const_iterator aIt = maPalette.begin(), aEnd = maPalette.end(); aIt != aEnd; ++aIt )
503 rStrm << aIt->maColor;
506 void XclExpPaletteImpl::SaveXml( XclExpXmlStream& rStrm )
508 if( !maPalette.size() )
509 return;
511 sax_fastparser::FSHelperPtr& rStyleSheet = rStrm.GetCurrentStream();
512 rStyleSheet->startElement( XML_colors, FSEND );
513 rStyleSheet->startElement( XML_indexedColors, FSEND );
514 for( XclPaletteColorVec::const_iterator aIt = maPalette.begin(), aEnd = maPalette.end(); aIt != aEnd; ++aIt )
515 rStyleSheet->singleElement( XML_rgbColor,
516 XML_rgb, XclXmlUtils::ToOString( aIt->maColor ).getStr(),
517 FSEND );
518 rStyleSheet->endElement( XML_indexedColors );
519 rStyleSheet->endElement( XML_colors );
522 const Color& XclExpPaletteImpl::GetOriginalColor( sal_uInt32 nColorId ) const
524 if( nColorId < maColorIdDataVec.size() )
525 return maColorIdDataVec[ nColorId ].maColor;
526 return maPalette[ 0 ].maColor;
529 XclListColor* XclExpPaletteImpl::SearchListEntry( const Color& rColor, sal_uInt32& rnIndex )
531 rnIndex = mnLastIdx;
532 XclListColor* pEntry = mxColorList->GetObject( rnIndex );
534 // search optimization for equal-colored objects occuring repeatedly
535 if( pEntry && (pEntry->GetColor() == rColor) )
536 return pEntry;
538 // binary search for color
539 sal_uInt32 nBegIdx = 0;
540 sal_uInt32 nEndIdx = mxColorList->Count();
541 bool bFound = false;
542 while( !bFound && (nBegIdx < nEndIdx) )
544 rnIndex = (nBegIdx + nEndIdx) / 2;
545 pEntry = mxColorList->GetObject( rnIndex );
546 bFound = pEntry->GetColor() == rColor;
547 if( !bFound )
549 if( pEntry->GetColor().GetColor() < rColor.GetColor() )
550 nBegIdx = rnIndex + 1;
551 else
552 nEndIdx = rnIndex;
555 // not found - use end of range as new insertion position
556 if( !bFound )
557 pEntry = mxColorList->GetObject( rnIndex = nEndIdx );
559 mnLastIdx = rnIndex;
560 return pEntry;
563 XclListColor* XclExpPaletteImpl::CreateListEntry( const Color& rColor, sal_uInt32 nIndex )
565 XclListColor* pEntry = new XclListColor( rColor, mxColorList->Count() );
566 mxColorList->Insert( pEntry, nIndex );
567 return pEntry;
570 void XclExpPaletteImpl::RawReducePalette( sal_uInt32 nPass )
572 /* Fast palette reduction - in each call of this function one RGB component
573 of each color is reduced to a lower number of distinct values.
574 Pass 0: Blue is reduced to 128 distinct values.
575 Pass 1: Red is reduced to 128 distinct values.
576 Pass 2: Green is reduced to 128 distinct values.
577 Pass 3: Blue is reduced to 64 distinct values.
578 Pass 4: Red is reduced to 64 distinct values.
579 Pass 5: Green is reduced to 64 distinct values.
580 And so on...
583 XclListColorListRef xOldList = mxColorList;
584 mxColorList.reset( new XclListColorList );
586 // maps old list indexes to new list indexes, used to update maColorIdDataVec
587 ScfUInt32Vec aListIndexMap;
588 aListIndexMap.reserve( xOldList->Count() );
590 // preparations
591 sal_uInt8 nR, nG, nB;
592 sal_uInt8& rnComp = ((nPass % 3 == 0) ? nB : ((nPass % 3 == 1) ? nR : nG));
593 nPass /= 3;
594 DBG_ASSERT( nPass < 7, "XclExpPaletteImpl::RawReducePalette - reduction not terminated" );
596 static const sal_uInt8 spnFactor2[] = { 0x81, 0x82, 0x84, 0x88, 0x92, 0xAA, 0xFF };
597 sal_uInt8 nFactor1 = static_cast< sal_uInt8 >( 0x02 << nPass );
598 sal_uInt8 nFactor2 = spnFactor2[ nPass ];
599 sal_uInt8 nFactor3 = static_cast< sal_uInt8 >( 0x40 >> nPass );
601 // process each color in the old color list
602 for( sal_uInt32 nIdx = 0, nCount = xOldList->Count(); nIdx < nCount; ++nIdx )
604 // get the old list entry
605 const XclListColor* pOldEntry = xOldList->GetObject( nIdx );
606 nR = pOldEntry->GetColor().GetRed();
607 nG = pOldEntry->GetColor().GetGreen();
608 nB = pOldEntry->GetColor().GetBlue();
610 /* Calculate the new RGB component (rnComp points to one of nR, nG, nB).
611 Using integer arithmetic with its rounding errors, the results of
612 this calculation are always exactly in the range 0x00 to 0xFF
613 (simply cutting the lower bits would darken the colors slightly). */
614 sal_uInt32 nNewComp = rnComp;
615 nNewComp /= nFactor1;
616 nNewComp *= nFactor2;
617 nNewComp /= nFactor3;
618 rnComp = static_cast< sal_uInt8 >( nNewComp );
619 Color aNewColor( nR, nG, nB );
621 // find or insert the new color
622 sal_uInt32 nFoundIdx = 0;
623 XclListColor* pNewEntry = SearchListEntry( aNewColor, nFoundIdx );
624 if( !pNewEntry || (pNewEntry->GetColor() != aNewColor) )
625 pNewEntry = CreateListEntry( aNewColor, nFoundIdx );
626 pNewEntry->AddWeighting( pOldEntry->GetWeighting() );
627 aListIndexMap.push_back( nFoundIdx );
630 // update color ID data map (maps color IDs to color list indexes), replace old by new list indexes
631 for( XclColorIdDataVec::iterator aIt = maColorIdDataVec.begin(), aEnd = maColorIdDataVec.end(); aIt != aEnd; ++aIt )
632 aIt->mnIndex = aListIndexMap[ aIt->mnIndex ];
635 void XclExpPaletteImpl::ReduceLeastUsedColor()
637 // find a list color to remove
638 sal_uInt32 nRemove = GetLeastUsedListColor();
639 // find its nearest neighbor
640 sal_uInt32 nKeep = GetNearestListColor( nRemove );
642 // merge both colors to one color, remove one color from list
643 XclListColor* pKeepEntry = mxColorList->GetObject( nKeep );
644 XclListColor* pRemoveEntry = mxColorList->GetObject( nRemove );
645 if( pKeepEntry && pRemoveEntry )
647 // merge both colors (if pKeepEntry is a base color, it will not change)
648 pKeepEntry->Merge( *pRemoveEntry );
649 // remove the less used color, adjust nKeep index if kept color follows removed color
650 mxColorList->Delete( nRemove );
651 if( nKeep > nRemove ) --nKeep;
653 // recalculate color ID data map (maps color IDs to color list indexes)
654 for( XclColorIdDataVec::iterator aIt = maColorIdDataVec.begin(), aEnd = maColorIdDataVec.end(); aIt != aEnd; ++aIt )
656 if( aIt->mnIndex > nRemove )
657 --aIt->mnIndex;
658 else if( aIt->mnIndex == nRemove )
659 aIt->mnIndex = nKeep;
664 sal_uInt32 XclExpPaletteImpl::GetLeastUsedListColor() const
666 sal_uInt32 nFound = 0;
667 sal_uInt32 nMinW = SAL_MAX_UINT32;
669 for( sal_uInt32 nIdx = 0, nCount = mxColorList->Count(); nIdx < nCount; ++nIdx )
671 XclListColor* pEntry = mxColorList->GetObject( nIdx );
672 // ignore the base colors
673 if( !pEntry->IsBaseColor() && (pEntry->GetWeighting() < nMinW) )
675 nFound = nIdx;
676 nMinW = pEntry->GetWeighting();
679 return nFound;
682 sal_uInt32 XclExpPaletteImpl::GetNearestListColor( const Color& rColor, sal_uInt32 nIgnore ) const
684 sal_uInt32 nFound = 0;
685 sal_Int32 nMinD = SAL_MAX_INT32;
687 for( sal_uInt32 nIdx = 0, nCount = mxColorList->Count(); nIdx < nCount; ++nIdx )
689 if( nIdx != nIgnore )
691 if( XclListColor* pEntry = mxColorList->GetObject( nIdx ) )
693 sal_Int32 nDist = lclGetColorDistance( rColor, pEntry->GetColor() );
694 if( nDist < nMinD )
696 nFound = nIdx;
697 nMinD = nDist;
702 return nFound;
705 sal_uInt32 XclExpPaletteImpl::GetNearestListColor( sal_uInt32 nIndex ) const
707 XclListColor* pEntry = mxColorList->GetObject( nIndex );
708 return pEntry ? GetNearestListColor( pEntry->GetColor(), nIndex ) : 0;
711 sal_Int32 XclExpPaletteImpl::GetNearestPaletteColor(
712 sal_uInt32& rnIndex, const Color& rColor, bool bDefaultOnly ) const
714 rnIndex = 0;
715 sal_Int32 nDist = SAL_MAX_INT32;
717 for( XclPaletteColorVec::const_iterator aIt = maPalette.begin(), aEnd = maPalette.end();
718 aIt != aEnd; ++aIt )
720 if( !bDefaultOnly || !aIt->mbUsed )
722 sal_Int32 nCurrDist = lclGetColorDistance( rColor, aIt->maColor );
723 if( nCurrDist < nDist )
725 rnIndex = aIt - maPalette.begin();
726 nDist = nCurrDist;
730 return nDist;
733 sal_Int32 XclExpPaletteImpl::GetNearPaletteColors(
734 sal_uInt32& rnFirst, sal_uInt32& rnSecond, const Color& rColor ) const
736 rnFirst = rnSecond = 0;
737 sal_Int32 nDist1 = SAL_MAX_INT32;
738 sal_Int32 nDist2 = SAL_MAX_INT32;
740 for( XclPaletteColorVec::const_iterator aIt = maPalette.begin(), aEnd = maPalette.end();
741 aIt != aEnd; ++aIt )
743 sal_Int32 nCurrDist = lclGetColorDistance( rColor, aIt->maColor );
744 if( nCurrDist < nDist1 )
746 rnSecond = rnFirst;
747 nDist2 = nDist1;
748 rnFirst = aIt - maPalette.begin();
749 nDist1 = nCurrDist;
751 else if( nCurrDist < nDist2 )
753 rnSecond = aIt - maPalette.begin();
754 nDist2 = nCurrDist;
757 return nDist1;
760 // ----------------------------------------------------------------------------
762 XclExpPalette::XclExpPalette( const XclExpRoot& rRoot ) :
763 XclDefaultPalette( rRoot ),
764 XclExpRecord( EXC_ID_PALETTE )
766 mxImpl.reset( new XclExpPaletteImpl( *this ) );
767 SetRecSize( GetColorCount() * 4 + 2 );
770 XclExpPalette::~XclExpPalette()
774 sal_uInt32 XclExpPalette::InsertColor( const Color& rColor, XclExpColorType eType, sal_uInt16 nAutoDefault )
776 return mxImpl->InsertColor( rColor, eType, nAutoDefault );
779 sal_uInt32 XclExpPalette::GetColorIdFromIndex( sal_uInt16 nIndex )
781 return XclExpPaletteImpl::GetColorIdFromIndex( nIndex );
784 void XclExpPalette::Finalize()
786 mxImpl->Finalize();
789 sal_uInt16 XclExpPalette::GetColorIndex( sal_uInt32 nColorId ) const
791 return mxImpl->GetColorIndex( nColorId );
794 void XclExpPalette::GetMixedColors(
795 sal_uInt16& rnXclForeIx, sal_uInt16& rnXclBackIx, sal_uInt8& rnXclPattern,
796 sal_uInt32 nForeColorId, sal_uInt32 nBackColorId ) const
798 return mxImpl->GetMixedColors( rnXclForeIx, rnXclBackIx, rnXclPattern, nForeColorId, nBackColorId );
801 ColorData XclExpPalette::GetColorData( sal_uInt16 nXclIndex ) const
803 return mxImpl->GetColorData( nXclIndex );
806 void XclExpPalette::Save( XclExpStream& rStrm )
808 if( !mxImpl->IsDefaultPalette() )
809 XclExpRecord::Save( rStrm );
812 void XclExpPalette::SaveXml( XclExpXmlStream& rStrm )
814 if( !mxImpl->IsDefaultPalette() )
815 mxImpl->SaveXml( rStrm );
818 void XclExpPalette::WriteBody( XclExpStream& rStrm )
820 mxImpl->WriteBody( rStrm );
823 // FONT record - font information =============================================
825 namespace {
827 sal_uInt32 lclCalcHash( const XclFontData& rFontData )
829 sal_uInt32 nHash = rFontData.maName.Len();
830 nHash += rFontData.maColor.GetColor() * 2;
831 nHash += rFontData.mnWeight * 3;
832 nHash += rFontData.mnCharSet * 5;
833 nHash += rFontData.mnFamily * 7;
834 nHash += rFontData.mnHeight * 11;
835 nHash += rFontData.mnUnderline * 13;
836 nHash += rFontData.mnEscapem * 17;
837 if( rFontData.mbItalic ) nHash += 19;
838 if( rFontData.mbStrikeout ) nHash += 23;
839 if( rFontData.mbOutline ) nHash += 29;
840 if( rFontData.mbShadow ) nHash += 31;
841 return nHash;
844 } // namespace
846 // ----------------------------------------------------------------------------
848 XclExpFont::XclExpFont( const XclExpRoot& rRoot,
849 const XclFontData& rFontData, XclExpColorType eColorType ) :
850 XclExpRecord( EXC_ID2_FONT, 14 ),
851 XclExpRoot( rRoot ),
852 maData( rFontData )
854 // insert font color into palette
855 mnColorId = rRoot.GetPalette().InsertColor( rFontData.maColor, eColorType, EXC_COLOR_FONTAUTO );
856 // hash value for faster comparison
857 mnHash = lclCalcHash( maData );
858 // record size
859 sal_Size nStrLen = maData.maName.Len();
860 SetRecSize( ((GetBiff() == EXC_BIFF8) ? (nStrLen * 2 + 1) : nStrLen) + 15 );
863 bool XclExpFont::Equals( const XclFontData& rFontData, sal_uInt32 nHash ) const
865 return (mnHash == nHash) && (maData == rFontData);
868 void XclExpFont::SaveXml( XclExpXmlStream& rStrm )
870 sax_fastparser::FSHelperPtr& rStyleSheet = rStrm.GetCurrentStream();
871 rStyleSheet->startElement( XML_font, FSEND );
872 rStrm.WriteFontData( maData, XML_name );
873 // OOXTODO: XML_scheme; //scheme/@val values: "major", "minor", "none"
874 rStyleSheet->endElement( XML_font );
877 // private --------------------------------------------------------------------
879 void XclExpFont::WriteBody( XclExpStream& rStrm )
881 sal_uInt16 nAttr = EXC_FONTATTR_NONE;
882 ::set_flag( nAttr, EXC_FONTATTR_ITALIC, maData.mbItalic );
883 ::set_flag( nAttr, EXC_FONTATTR_STRIKEOUT, maData.mbStrikeout );
884 ::set_flag( nAttr, EXC_FONTATTR_OUTLINE, maData.mbOutline );
885 ::set_flag( nAttr, EXC_FONTATTR_SHADOW, maData.mbShadow );
887 DBG_ASSERT( maData.maName.Len() < 256, "XclExpFont::WriteBody - font name too long" );
888 XclExpString aFontName;
889 if( GetBiff() <= EXC_BIFF5 )
890 aFontName.AssignByte( maData.maName, GetTextEncoding(), EXC_STR_8BITLENGTH );
891 else
892 aFontName.Assign( maData.maName, EXC_STR_FORCEUNICODE | EXC_STR_8BITLENGTH );
894 rStrm << maData.mnHeight
895 << nAttr
896 << GetPalette().GetColorIndex( mnColorId )
897 << maData.mnWeight
898 << maData.mnEscapem
899 << maData.mnUnderline
900 << maData.mnFamily
901 << maData.mnCharSet
902 << sal_uInt8( 0 )
903 << aFontName;
906 // ----------------------------------------------------------------------------
908 XclExpBlindFont::XclExpBlindFont( const XclExpRoot& rRoot ) :
909 XclExpFont( rRoot, XclFontData(), EXC_COLOR_CELLTEXT )
913 bool XclExpBlindFont::Equals( const XclFontData& /*rFontData*/, sal_uInt32 /*nHash*/ ) const
915 return false;
918 void XclExpBlindFont::Save( XclExpStream& /*rStrm*/ )
920 // do nothing
923 // ============================================================================
925 XclExpFontBuffer::XclExpFontBuffer( const XclExpRoot& rRoot ) :
926 XclExpRoot( rRoot ),
927 mnXclMaxSize( 0 )
929 switch( GetBiff() )
931 case EXC_BIFF4: mnXclMaxSize = EXC_FONT_MAXCOUNT4; break;
932 case EXC_BIFF5: mnXclMaxSize = EXC_FONT_MAXCOUNT5; break;
933 case EXC_BIFF8: mnXclMaxSize = EXC_FONT_MAXCOUNT8; break;
934 default: DBG_ERROR_BIFF();
936 InitDefaultFonts();
939 const XclExpFont* XclExpFontBuffer::GetFont( sal_uInt16 nXclFont ) const
941 return maFontList.GetRecord( nXclFont ).get();
944 const XclFontData& XclExpFontBuffer::GetAppFontData() const
946 return maFontList.GetRecord( EXC_FONT_APP )->GetFontData(); // exists always
949 sal_uInt16 XclExpFontBuffer::Insert(
950 const XclFontData& rFontData, XclExpColorType eColorType, bool bAppFont )
952 if( bAppFont )
954 XclExpFontRef xFont( new XclExpFont( GetRoot(), rFontData, eColorType ) );
955 maFontList.ReplaceRecord( xFont, EXC_FONT_APP );
956 // #108487# set width of '0' character for column width export
957 SetCharWidth( xFont->GetFontData() );
958 return EXC_FONT_APP;
961 size_t nPos = Find( rFontData );
962 if( nPos == EXC_FONTLIST_NOTFOUND )
964 // not found in buffer - create new font
965 size_t nSize = maFontList.GetSize();
966 if( nSize < mnXclMaxSize )
968 // possible to insert
969 maFontList.AppendNewRecord( new XclExpFont( GetRoot(), rFontData, eColorType ) );
970 nPos = nSize; // old size is last position now
972 else
974 // buffer is full - ignore new font, use default font
975 nPos = EXC_FONT_APP;
978 return static_cast< sal_uInt16 >( nPos );
981 sal_uInt16 XclExpFontBuffer::Insert(
982 const Font& rFont, XclExpColorType eColorType, bool bAppFont )
984 return Insert( XclFontData( rFont ), eColorType, bAppFont );
987 sal_uInt16 XclExpFontBuffer::Insert(
988 const SvxFont& rFont, XclExpColorType eColorType, bool bAppFont )
990 return Insert( XclFontData( rFont ), eColorType, bAppFont );
993 sal_uInt16 XclExpFontBuffer::Insert( const SfxItemSet& rItemSet,
994 sal_Int16 nScript, XclExpColorType eColorType, bool bAppFont )
996 // #i17050# #114008# #115495# script type now provided by caller
997 return Insert( GetFontFromItemSet( rItemSet, nScript ), eColorType, bAppFont );
1000 sal_uInt16 XclExpFontBuffer::Insert( const ScPatternAttr& rPattern,
1001 sal_Int16 nScript, XclExpColorType eColorType, bool bAppFont )
1003 return Insert( rPattern.GetItemSet(), nScript, eColorType, bAppFont );
1006 void XclExpFontBuffer::Save( XclExpStream& rStrm )
1008 maFontList.Save( rStrm );
1011 void XclExpFontBuffer::SaveXml( XclExpXmlStream& rStrm )
1013 if( maFontList.IsEmpty() )
1014 return;
1016 sax_fastparser::FSHelperPtr& rStyleSheet = rStrm.GetCurrentStream();
1017 rStyleSheet->startElement( XML_fonts,
1018 XML_count, OString::valueOf( (sal_Int32) maFontList.GetSize() ).getStr(),
1019 FSEND );
1021 maFontList.SaveXml( rStrm );
1023 rStyleSheet->endElement( XML_fonts );
1026 sal_Int16 XclExpFontBuffer::GetFirstUsedScript( const SfxItemSet& rItemSet )
1028 /* #i17050# We need to determine if a CJK or CTL font item is set in the
1029 item set. It is possible that both may be present. In this case,
1030 we will choose CJK. Either option is equally correct. */
1032 namespace ApiScriptType = ::com::sun::star::i18n::ScriptType;
1033 sal_Int16 nScript = ApiScriptType::LATIN;
1035 // #114008# do not let a font from a parent style override an explicit cell font
1036 const SfxItemSet* pCurrSet = &rItemSet;
1037 bool bFound = false;
1038 while( !bFound && pCurrSet )
1040 bFound = true;
1041 if( ScfTools::CheckItem( *pCurrSet, ATTR_CJK_FONT, false ) )
1042 nScript = ApiScriptType::ASIAN;
1043 else if( ScfTools::CheckItem( *pCurrSet, ATTR_CTL_FONT, false ) )
1044 nScript = ApiScriptType::COMPLEX;
1045 else if( ScfTools::CheckItem( *pCurrSet, ATTR_FONT, false ) )
1046 nScript = ApiScriptType::LATIN;
1047 else
1048 bFound = false;
1049 pCurrSet = pCurrSet->GetParent();
1052 return nScript;
1055 Font XclExpFontBuffer::GetFontFromItemSet( const SfxItemSet& rItemSet, sal_Int16 nScript )
1057 namespace ApiScriptType = ::com::sun::star::i18n::ScriptType;
1059 // if WEAK is passed, guess script type from existing items in the item set
1060 if( nScript == ApiScriptType::WEAK )
1061 nScript = GetFirstUsedScript( rItemSet );
1063 // convert to core script type constants
1064 BYTE nScScript = SCRIPTTYPE_LATIN;
1065 switch( nScript )
1067 case ApiScriptType::LATIN: nScScript = SCRIPTTYPE_LATIN; break;
1068 case ApiScriptType::ASIAN: nScScript = SCRIPTTYPE_ASIAN; break;
1069 case ApiScriptType::COMPLEX: nScScript = SCRIPTTYPE_COMPLEX; break;
1070 default: DBG_ERRORFILE( "XclExpFontBuffer::GetFontFromItemSet - unknown script type" );
1073 // fill the font object
1074 Font aFont;
1075 ScPatternAttr::GetFont( aFont, rItemSet, SC_AUTOCOL_RAW, 0, 0, 0, nScScript );
1076 return aFont;
1079 bool XclExpFontBuffer::CheckItems( const SfxItemSet& rItemSet, sal_Int16 nScript, bool bDeep )
1081 static const USHORT pnCommonIds[] = {
1082 ATTR_FONT_UNDERLINE, ATTR_FONT_CROSSEDOUT, ATTR_FONT_CONTOUR,
1083 ATTR_FONT_SHADOWED, ATTR_FONT_COLOR, ATTR_FONT_LANGUAGE, 0 };
1084 static const USHORT pnLatinIds[] = {
1085 ATTR_FONT, ATTR_FONT_HEIGHT, ATTR_FONT_WEIGHT, ATTR_FONT_POSTURE, 0 };
1086 static const USHORT pnAsianIds[] = {
1087 ATTR_CJK_FONT, ATTR_CJK_FONT_HEIGHT, ATTR_CJK_FONT_WEIGHT, ATTR_CJK_FONT_POSTURE, 0 };
1088 static const USHORT pnComplexIds[] = {
1089 ATTR_CTL_FONT, ATTR_CTL_FONT_HEIGHT, ATTR_CTL_FONT_WEIGHT, ATTR_CTL_FONT_POSTURE, 0 };
1091 bool bUsed = ScfTools::CheckItems( rItemSet, pnCommonIds, bDeep );
1092 if( !bUsed )
1094 namespace ApiScriptType = ::com::sun::star::i18n::ScriptType;
1095 // if WEAK is passed, guess script type from existing items in the item set
1096 if( nScript == ApiScriptType::WEAK )
1097 nScript = GetFirstUsedScript( rItemSet );
1098 // check the correct items
1099 switch( nScript )
1101 case ApiScriptType::LATIN: bUsed = ScfTools::CheckItems( rItemSet, pnLatinIds, bDeep ); break;
1102 case ApiScriptType::ASIAN: bUsed = ScfTools::CheckItems( rItemSet, pnAsianIds, bDeep ); break;
1103 case ApiScriptType::COMPLEX: bUsed = ScfTools::CheckItems( rItemSet, pnComplexIds, bDeep ); break;
1104 default: DBG_ERRORFILE( "XclExpFontBuffer::CheckItems - unknown script type" );
1107 return bUsed;
1110 // private --------------------------------------------------------------------
1112 void XclExpFontBuffer::InitDefaultFonts()
1114 XclFontData aFontData;
1115 aFontData.maName.AssignAscii( "Arial" );
1116 aFontData.SetScFamily( FAMILY_DONTKNOW );
1117 aFontData.SetFontEncoding( ScfTools::GetSystemTextEncoding() );
1118 aFontData.SetScHeight( 200 ); // 200 twips = 10 pt
1119 aFontData.SetScWeight( WEIGHT_NORMAL );
1121 switch( GetBiff() )
1123 case EXC_BIFF5:
1125 maFontList.AppendNewRecord( new XclExpFont( GetRoot(), aFontData, EXC_COLOR_CELLTEXT ) );
1126 aFontData.SetScWeight( WEIGHT_BOLD );
1127 maFontList.AppendNewRecord( new XclExpFont( GetRoot(), aFontData, EXC_COLOR_CELLTEXT ) );
1128 aFontData.SetScWeight( WEIGHT_NORMAL );
1129 aFontData.SetScPosture( ITALIC_NORMAL );
1130 maFontList.AppendNewRecord( new XclExpFont( GetRoot(), aFontData, EXC_COLOR_CELLTEXT ) );
1131 aFontData.SetScWeight( WEIGHT_BOLD );
1132 maFontList.AppendNewRecord( new XclExpFont( GetRoot(), aFontData, EXC_COLOR_CELLTEXT ) );
1133 // the blind font with index 4
1134 maFontList.AppendNewRecord( new XclExpBlindFont( GetRoot() ) );
1135 // already add the first user defined font (Excel does it too)
1136 aFontData.SetScWeight( WEIGHT_NORMAL );
1137 aFontData.SetScPosture( ITALIC_NONE );
1138 maFontList.AppendNewRecord( new XclExpFont( GetRoot(), aFontData, EXC_COLOR_CELLTEXT ) );
1140 break;
1141 case EXC_BIFF8:
1143 XclExpFontRef xFont( new XclExpFont( GetRoot(), aFontData, EXC_COLOR_CELLTEXT ) );
1144 maFontList.AppendRecord( xFont );
1145 maFontList.AppendRecord( xFont );
1146 maFontList.AppendRecord( xFont );
1147 maFontList.AppendRecord( xFont );
1148 if( GetOutput() == EXC_OUTPUT_BINARY )
1149 // the blind font with index 4
1150 maFontList.AppendNewRecord( new XclExpBlindFont( GetRoot() ) );
1152 break;
1153 default:
1154 DBG_ERROR_BIFF();
1158 size_t XclExpFontBuffer::Find( const XclFontData& rFontData )
1160 sal_uInt32 nHash = lclCalcHash( rFontData );
1161 for( size_t nPos = 0, nSize = maFontList.GetSize(); nPos < nSize; ++nPos )
1162 if( maFontList.GetRecord( nPos )->Equals( rFontData, nHash ) )
1163 return nPos;
1164 return EXC_FONTLIST_NOTFOUND;
1167 // FORMAT record - number formats =============================================
1169 /** Predicate for search algorithm. */
1170 struct XclExpNumFmtPred
1172 ULONG mnScNumFmt;
1173 inline explicit XclExpNumFmtPred( ULONG nScNumFmt ) : mnScNumFmt( nScNumFmt ) {}
1174 inline bool operator()( const XclExpNumFmt& rFormat ) const
1175 { return rFormat.mnScNumFmt == mnScNumFmt; }
1178 // ----------------------------------------------------------------------------
1180 XclExpNumFmtBuffer::XclExpNumFmtBuffer( const XclExpRoot& rRoot ) :
1181 XclExpRoot( rRoot ),
1182 /* Compiler needs a hint, this doesn't work: new NfKeywordTable;
1183 cannot convert from 'class String *' to 'class String (*)[54]'
1184 The effective result here is class String (*)[54*1] */
1185 mxFormatter( new SvNumberFormatter( rRoot.GetDoc().GetServiceManager(), LANGUAGE_ENGLISH_US ) ),
1186 mpKeywordTable( new NfKeywordTable[ 1 ] ),
1187 mnStdFmt( GetFormatter().GetStandardFormat( ScGlobal::eLnge ) )
1189 switch( GetBiff() )
1191 case EXC_BIFF5: mnXclOffset = EXC_FORMAT_OFFSET5; break;
1192 case EXC_BIFF8: mnXclOffset = EXC_FORMAT_OFFSET8; break;
1193 default: DBG_ERROR_BIFF();
1196 mxFormatter->FillKeywordTable( *mpKeywordTable, LANGUAGE_ENGLISH_US );
1197 // remap codes unknown to Excel
1198 (*mpKeywordTable)[ NF_KEY_NN ] = String( RTL_CONSTASCII_USTRINGPARAM( "DDD" ) );
1199 (*mpKeywordTable)[ NF_KEY_NNN ] = String( RTL_CONSTASCII_USTRINGPARAM( "DDDD" ) );
1200 // NNNN gets a separator appended in SvNumberformat::GetMappedFormatString()
1201 (*mpKeywordTable)[ NF_KEY_NNNN ] = String( RTL_CONSTASCII_USTRINGPARAM( "DDDD" ) );
1202 // Export the Thai T NatNum modifier.
1203 (*mpKeywordTable)[ NF_KEY_THAI_T ] = String( RTL_CONSTASCII_USTRINGPARAM( "T" ) );
1206 XclExpNumFmtBuffer::~XclExpNumFmtBuffer()
1208 delete[] mpKeywordTable;
1211 sal_uInt16 XclExpNumFmtBuffer::Insert( ULONG nScNumFmt )
1213 XclExpNumFmtVec::const_iterator aIt =
1214 ::std::find_if( maFormatMap.begin(), maFormatMap.end(), XclExpNumFmtPred( nScNumFmt ) );
1215 if( aIt != maFormatMap.end() )
1216 return aIt->mnXclNumFmt;
1218 size_t nSize = maFormatMap.size();
1219 if( nSize < static_cast< size_t >( 0xFFFF - mnXclOffset ) )
1221 sal_uInt16 nXclNumFmt = static_cast< sal_uInt16 >( nSize + mnXclOffset );
1222 maFormatMap.push_back( XclExpNumFmt( nScNumFmt, nXclNumFmt ) );
1223 return nXclNumFmt;
1226 return 0;
1229 void XclExpNumFmtBuffer::Save( XclExpStream& rStrm )
1231 for( XclExpNumFmtVec::const_iterator aIt = maFormatMap.begin(), aEnd = maFormatMap.end(); aIt != aEnd; ++aIt )
1232 WriteFormatRecord( rStrm, *aIt );
1235 void XclExpNumFmtBuffer::SaveXml( XclExpXmlStream& rStrm )
1237 if( !maFormatMap.size() )
1238 return;
1240 sax_fastparser::FSHelperPtr& rStyleSheet = rStrm.GetCurrentStream();
1241 rStyleSheet->startElement( XML_numFmts,
1242 XML_count, OString::valueOf( (sal_Int32) maFormatMap.size() ).getStr(),
1243 FSEND );
1244 for( XclExpNumFmtVec::const_iterator aIt = maFormatMap.begin(), aEnd = maFormatMap.end(); aIt != aEnd; ++aIt )
1246 rStyleSheet->singleElement( XML_numFmt,
1247 XML_numFmtId, OString::valueOf( sal_Int32(aIt->mnXclNumFmt) ).getStr(),
1248 XML_formatCode, XclXmlUtils::ToOString( GetFormatCode( *aIt ) ).getStr(),
1249 FSEND );
1251 rStyleSheet->endElement( XML_numFmts );
1254 void XclExpNumFmtBuffer::WriteFormatRecord( XclExpStream& rStrm, sal_uInt16 nXclNumFmt, const String& rFormatStr )
1256 XclExpString aExpStr;
1257 if( GetBiff() <= EXC_BIFF5 )
1258 aExpStr.AssignByte( rFormatStr, GetTextEncoding(), EXC_STR_8BITLENGTH );
1259 else
1260 aExpStr.Assign( rFormatStr );
1262 rStrm.StartRecord( EXC_ID4_FORMAT, 2 + aExpStr.GetSize() );
1263 rStrm << nXclNumFmt << aExpStr;
1264 rStrm.EndRecord();
1267 void XclExpNumFmtBuffer::WriteFormatRecord( XclExpStream& rStrm, const XclExpNumFmt& rFormat )
1269 WriteFormatRecord( rStrm, rFormat.mnXclNumFmt, GetFormatCode( rFormat ) );
1272 String XclExpNumFmtBuffer::GetFormatCode( const XclExpNumFmt& rFormat )
1274 String aFormatStr;
1276 if( const SvNumberformat* pEntry = GetFormatter().GetEntry( rFormat.mnScNumFmt ) )
1278 if( pEntry->GetType() == NUMBERFORMAT_LOGICAL )
1280 // build Boolean number format
1281 Color* pColor = 0;
1282 String aTemp;
1283 const_cast< SvNumberformat* >( pEntry )->GetOutputString( 1.0, aTemp, &pColor );
1284 aFormatStr.Append( '"' ).Append( aTemp ).AppendAscii( "\";\"" ).Append( aTemp ).AppendAscii( "\";\"" );
1285 const_cast< SvNumberformat* >( pEntry )->GetOutputString( 0.0, aTemp, &pColor );
1286 aFormatStr.Append( aTemp ).Append( '"' );
1288 else
1290 LanguageType eLang = pEntry->GetLanguage();
1291 if( eLang != LANGUAGE_ENGLISH_US )
1293 xub_StrLen nCheckPos;
1294 short nType = NUMBERFORMAT_DEFINED;
1295 sal_uInt32 nKey;
1296 String aTemp( pEntry->GetFormatstring() );
1297 mxFormatter->PutandConvertEntry( aTemp, nCheckPos, nType, nKey, eLang, LANGUAGE_ENGLISH_US );
1298 DBG_ASSERT( nCheckPos == 0, "XclExpNumFmtBuffer::WriteFormatRecord - format code not convertible" );
1299 pEntry = mxFormatter->GetEntry( nKey );
1302 aFormatStr = pEntry->GetMappedFormatstring( *mpKeywordTable, *mxFormatter->GetLocaleData() );
1303 if( aFormatStr.EqualsAscii( "Standard" ) )
1304 aFormatStr.AssignAscii( "General" );
1307 else
1309 DBG_ERRORFILE( "XclExpNumFmtBuffer::WriteFormatRecord - format not found" );
1310 aFormatStr.AssignAscii( "General" );
1313 return aFormatStr;
1316 // XF, STYLE record - Cell formatting =========================================
1318 bool XclExpCellProt::FillFromItemSet( const SfxItemSet& rItemSet, bool bStyle )
1320 const ScProtectionAttr& rProtItem = GETITEM( rItemSet, ScProtectionAttr, ATTR_PROTECTION );
1321 mbLocked = rProtItem.GetProtection();
1322 mbHidden = rProtItem.GetHideFormula() || rProtItem.GetHideCell();
1323 return ScfTools::CheckItem( rItemSet, ATTR_PROTECTION, bStyle );
1326 #if 0
1327 void XclExpCellProt::FillToXF2( sal_uInt8& rnNumFmt ) const
1329 ::set_flag( rnNumFmt, EXC_XF2_LOCKED, mbLocked );
1330 ::set_flag( rnNumFmt, EXC_XF2_HIDDEN, mbHidden );
1332 #endif
1334 void XclExpCellProt::FillToXF3( sal_uInt16& rnProt ) const
1336 ::set_flag( rnProt, EXC_XF_LOCKED, mbLocked );
1337 ::set_flag( rnProt, EXC_XF_HIDDEN, mbHidden );
1340 void XclExpCellProt::SaveXml( XclExpXmlStream& rStrm ) const
1342 rStrm.GetCurrentStream()->singleElement( XML_protection,
1343 XML_locked, XclXmlUtils::ToPsz( mbLocked ),
1344 XML_hidden, XclXmlUtils::ToPsz( mbHidden ),
1345 FSEND );
1348 // ----------------------------------------------------------------------------
1350 bool XclExpCellAlign::FillFromItemSet(
1351 const SfxItemSet& rItemSet, bool bForceLineBreak, XclBiff eBiff, bool bStyle )
1353 bool bUsed = false;
1355 switch( eBiff )
1357 // ALL 'case's - run through!
1359 case EXC_BIFF8: // attributes new in BIFF8
1361 // text indent
1362 long nTmpIndent = GETITEMVALUE( rItemSet, SfxUInt16Item, ATTR_INDENT, sal_Int32 );
1363 (nTmpIndent += 100) /= 200; // 1 Excel unit == 10 pt == 200 twips
1364 mnIndent = limit_cast< sal_uInt8 >( nTmpIndent, 0, 15 );
1365 bUsed |= ScfTools::CheckItem( rItemSet, ATTR_INDENT, bStyle );
1367 // shrink to fit
1368 mbShrink = GETITEMVALUE( rItemSet, SfxBoolItem, ATTR_SHRINKTOFIT, BOOL );
1369 bUsed |= ScfTools::CheckItem( rItemSet, ATTR_SHRINKTOFIT, bStyle );
1371 // CTL text direction
1372 SetScFrameDir( GETITEMVALUE( rItemSet, SvxFrameDirectionItem, ATTR_WRITINGDIR, SvxFrameDirection ) );
1373 bUsed |= ScfTools::CheckItem( rItemSet, ATTR_WRITINGDIR, bStyle );
1376 case EXC_BIFF5: // attributes new in BIFF5
1377 case EXC_BIFF4: // attributes new in BIFF4
1379 // vertical alignment
1380 SetScVerAlign( GETITEMVALUE( rItemSet, SvxVerJustifyItem, ATTR_VER_JUSTIFY, SvxCellVerJustify ) );
1381 bUsed |= ScfTools::CheckItem( rItemSet, ATTR_VER_JUSTIFY, bStyle );
1383 // stacked/rotation
1384 bool bStacked = GETITEMVALUE( rItemSet, SfxBoolItem, ATTR_STACKED, BOOL );
1385 bUsed |= ScfTools::CheckItem( rItemSet, ATTR_STACKED, bStyle );
1386 if( bStacked )
1388 mnRotation = EXC_ROT_STACKED;
1390 else
1392 // rotation
1393 sal_Int32 nScRot = GETITEMVALUE( rItemSet, SfxInt32Item, ATTR_ROTATE_VALUE, sal_Int32 );
1394 mnRotation = XclTools::GetXclRotation( nScRot );
1395 bUsed |= ScfTools::CheckItem( rItemSet, ATTR_ROTATE_VALUE, bStyle );
1397 mnOrient = XclTools::GetXclOrientFromRot( mnRotation );
1400 case EXC_BIFF3: // attributes new in BIFF3
1402 // text wrap
1403 mbLineBreak = bForceLineBreak || GETITEMBOOL( rItemSet, ATTR_LINEBREAK );
1404 bUsed |= bForceLineBreak || ScfTools::CheckItem( rItemSet, ATTR_LINEBREAK, bStyle );
1407 case EXC_BIFF2: // attributes new in BIFF2
1409 // horizontal alignment
1410 SetScHorAlign( GETITEMVALUE( rItemSet, SvxHorJustifyItem, ATTR_HOR_JUSTIFY, SvxCellHorJustify ) );
1411 bUsed |= ScfTools::CheckItem( rItemSet, ATTR_HOR_JUSTIFY, bStyle );
1414 break;
1415 default: DBG_ERROR_BIFF();
1418 return bUsed;
1421 #if 0
1422 void XclExpCellAlign::FillToXF2( sal_uInt8& rnFlags ) const
1424 ::insert_value( rnFlags, mnHorAlign, 0, 3 );
1427 void XclExpCellAlign::FillToXF3( sal_uInt16& rnAlign ) const
1429 ::insert_value( rnAlign, mnHorAlign, 0, 3 );
1430 ::set_flag( rnAlign, EXC_XF_LINEBREAK, mbLineBreak );
1433 void XclExpCellAlign::FillToXF4( sal_uInt16& rnAlign ) const
1435 FillToXF3( rnAlign );
1436 ::insert_value( rnAlign, mnVerAlign, 4, 2 );
1437 ::insert_value( rnAlign, mnOrient, 6, 2 );
1439 #endif
1441 void XclExpCellAlign::FillToXF5( sal_uInt16& rnAlign ) const
1443 ::insert_value( rnAlign, mnHorAlign, 0, 3 );
1444 ::set_flag( rnAlign, EXC_XF_LINEBREAK, mbLineBreak );
1445 ::insert_value( rnAlign, mnVerAlign, 4, 3 );
1446 ::insert_value( rnAlign, mnOrient, 8, 2 );
1449 void XclExpCellAlign::FillToXF8( sal_uInt16& rnAlign, sal_uInt16& rnMiscAttrib ) const
1451 ::insert_value( rnAlign, mnHorAlign, 0, 3 );
1452 ::set_flag( rnAlign, EXC_XF_LINEBREAK, mbLineBreak );
1453 ::insert_value( rnAlign, mnVerAlign, 4, 3 );
1454 ::insert_value( rnAlign, mnRotation, 8, 8 );
1455 ::insert_value( rnMiscAttrib, mnIndent, 0, 4 );
1456 ::set_flag( rnMiscAttrib, EXC_XF8_SHRINK, mbShrink );
1457 ::insert_value( rnMiscAttrib, mnTextDir, 6, 2 );
1460 static const char* ToHorizontalAlignment( sal_uInt8 nHorAlign )
1462 switch( nHorAlign )
1464 case EXC_XF_HOR_GENERAL: return "general";
1465 case EXC_XF_HOR_LEFT: return "left";
1466 case EXC_XF_HOR_CENTER: return "center";
1467 case EXC_XF_HOR_RIGHT: return "right";
1468 case EXC_XF_HOR_FILL: return "fill";
1469 case EXC_XF_HOR_JUSTIFY: return "justify";
1470 case EXC_XF_HOR_CENTER_AS: return "centerContinuous";
1471 case EXC_XF_HOR_DISTRIB: return "distributed";
1473 return "*unknown*";
1476 static const char* ToVerticalAlignment( sal_uInt8 nVerAlign )
1478 switch( nVerAlign )
1480 case EXC_XF_VER_TOP: return "top";
1481 case EXC_XF_VER_CENTER: return "center";
1482 case EXC_XF_VER_BOTTOM: return "bottom";
1483 case EXC_XF_VER_JUSTIFY: return "justify";
1484 case EXC_XF_VER_DISTRIB: return "distributed";
1486 return "*unknown*";
1489 void XclExpCellAlign::SaveXml( XclExpXmlStream& rStrm ) const
1491 rStrm.GetCurrentStream()->singleElement( XML_alignment,
1492 XML_horizontal, ToHorizontalAlignment( mnHorAlign ),
1493 XML_vertical, ToVerticalAlignment( mnVerAlign ),
1494 XML_textRotation, OString::valueOf( (sal_Int32) mnRotation ).getStr(),
1495 XML_wrapText, XclXmlUtils::ToPsz( mbLineBreak ),
1496 XML_indent, OString::valueOf( (sal_Int32) mnIndent ).getStr(),
1497 // OOXTODO: XML_relativeIndent, mnIndent?
1498 // OOXTODO: XML_justifyLastLine,
1499 XML_shrinkToFit, XclXmlUtils::ToPsz( mbShrink ),
1500 // OOXTODO: XML_readingOrder,
1501 FSEND );
1504 // ----------------------------------------------------------------------------
1506 namespace {
1508 void lclGetBorderLine(
1509 sal_uInt8& rnXclLine, sal_uInt32& rnColorId,
1510 const SvxBorderLine* pLine, XclExpPalette& rPalette, XclBiff eBiff )
1512 rnXclLine = EXC_LINE_NONE;
1513 if( pLine )
1515 sal_uInt16 nOuterWidth = pLine->GetOutWidth();
1516 sal_uInt16 nDistance = pLine->GetDistance();
1517 if( nDistance > 0 )
1518 rnXclLine = EXC_LINE_DOUBLE;
1519 else if( nOuterWidth > DEF_LINE_WIDTH_2 )
1520 rnXclLine = EXC_LINE_THICK;
1521 else if( nOuterWidth > DEF_LINE_WIDTH_1 )
1522 rnXclLine = EXC_LINE_MEDIUM;
1523 else if( nOuterWidth > DEF_LINE_WIDTH_0 )
1524 rnXclLine = EXC_LINE_THIN;
1525 else if( nOuterWidth > 0 )
1526 rnXclLine = EXC_LINE_HAIR;
1527 else
1528 rnXclLine = EXC_LINE_NONE;
1530 if( (eBiff == EXC_BIFF2) && (rnXclLine != EXC_LINE_NONE) )
1531 rnXclLine = EXC_LINE_THIN;
1533 rnColorId = (pLine && (rnXclLine != EXC_LINE_NONE)) ?
1534 rPalette.InsertColor( pLine->GetColor(), EXC_COLOR_CELLBORDER ) :
1535 XclExpPalette::GetColorIdFromIndex( 0 );
1538 } // namespace
1540 // ----------------------------------------------------------------------------
1542 XclExpCellBorder::XclExpCellBorder() :
1543 mnLeftColorId( XclExpPalette::GetColorIdFromIndex( mnLeftColor ) ),
1544 mnRightColorId( XclExpPalette::GetColorIdFromIndex( mnRightColor ) ),
1545 mnTopColorId( XclExpPalette::GetColorIdFromIndex( mnTopColor ) ),
1546 mnBottomColorId( XclExpPalette::GetColorIdFromIndex( mnBottomColor ) ),
1547 mnDiagColorId( XclExpPalette::GetColorIdFromIndex( mnDiagColor ) )
1551 bool XclExpCellBorder::FillFromItemSet(
1552 const SfxItemSet& rItemSet, XclExpPalette& rPalette, XclBiff eBiff, bool bStyle )
1554 bool bUsed = false;
1556 switch( eBiff )
1558 // ALL 'case's - run through!
1560 case EXC_BIFF8: // attributes new in BIFF8
1562 const SvxLineItem& rTLBRItem = GETITEM( rItemSet, SvxLineItem, ATTR_BORDER_TLBR );
1563 sal_uInt8 nTLBRLine;
1564 sal_uInt32 nTLBRColorId;
1565 lclGetBorderLine( nTLBRLine, nTLBRColorId, rTLBRItem.GetLine(), rPalette, eBiff );
1566 mbDiagTLtoBR = (nTLBRLine != EXC_LINE_NONE);
1568 const SvxLineItem& rBLTRItem = GETITEM( rItemSet, SvxLineItem, ATTR_BORDER_BLTR );
1569 sal_uInt8 nBLTRLine;
1570 sal_uInt32 nBLTRColorId;
1571 lclGetBorderLine( nBLTRLine, nBLTRColorId, rBLTRItem.GetLine(), rPalette, eBiff );
1572 mbDiagBLtoTR = (nBLTRLine != EXC_LINE_NONE);
1574 if( ::ScHasPriority( rTLBRItem.GetLine(), rBLTRItem.GetLine() ) )
1576 mnDiagLine = nTLBRLine;
1577 mnDiagColorId = nTLBRColorId;
1579 else
1581 mnDiagLine = nBLTRLine;
1582 mnDiagColorId = nBLTRColorId;
1585 bUsed |= ScfTools::CheckItem( rItemSet, ATTR_BORDER_TLBR, bStyle ) ||
1586 ScfTools::CheckItem( rItemSet, ATTR_BORDER_BLTR, bStyle );
1589 case EXC_BIFF5:
1590 case EXC_BIFF4:
1591 case EXC_BIFF3:
1592 case EXC_BIFF2:
1594 const SvxBoxItem& rBoxItem = GETITEM( rItemSet, SvxBoxItem, ATTR_BORDER );
1595 lclGetBorderLine( mnLeftLine, mnLeftColorId, rBoxItem.GetLeft(), rPalette, eBiff );
1596 lclGetBorderLine( mnRightLine, mnRightColorId, rBoxItem.GetRight(), rPalette, eBiff );
1597 lclGetBorderLine( mnTopLine, mnTopColorId, rBoxItem.GetTop(), rPalette, eBiff );
1598 lclGetBorderLine( mnBottomLine, mnBottomColorId, rBoxItem.GetBottom(), rPalette, eBiff );
1599 bUsed |= ScfTools::CheckItem( rItemSet, ATTR_BORDER, bStyle );
1602 break;
1603 default: DBG_ERROR_BIFF();
1606 return bUsed;
1609 void XclExpCellBorder::SetFinalColors( const XclExpPalette& rPalette )
1611 mnLeftColor = rPalette.GetColorIndex( mnLeftColorId );
1612 mnRightColor = rPalette.GetColorIndex( mnRightColorId );
1613 mnTopColor = rPalette.GetColorIndex( mnTopColorId );
1614 mnBottomColor = rPalette.GetColorIndex( mnBottomColorId );
1615 mnDiagColor = rPalette.GetColorIndex( mnDiagColorId );
1618 #if 0
1619 void XclExpCellBorder::FillToXF2( sal_uInt8& rnFlags ) const
1621 ::set_flag( rnFlags, EXC_XF2_LEFTLINE, mnLeftLine != EXC_LINE_NONE );
1622 ::set_flag( rnFlags, EXC_XF2_RIGHTLINE, mnRightLine != EXC_LINE_NONE );
1623 ::set_flag( rnFlags, EXC_XF2_TOPLINE, mnTopLine != EXC_LINE_NONE );
1624 ::set_flag( rnFlags, EXC_XF2_BOTTOMLINE, mnBottomLine != EXC_LINE_NONE );
1627 void XclExpCellBorder::FillToXF3( sal_uInt32& rnBorder ) const
1629 ::insert_value( rnBorder, mnTopLine, 0, 3 );
1630 ::insert_value( rnBorder, mnLeftLine, 8, 3 );
1631 ::insert_value( rnBorder, mnBottomLine, 16, 3 );
1632 ::insert_value( rnBorder, mnRightLine, 24, 3 );
1633 ::insert_value( rnBorder, mnTopColor, 3, 5 );
1634 ::insert_value( rnBorder, mnLeftColor, 11, 5 );
1635 ::insert_value( rnBorder, mnBottomColor, 19, 5 );
1636 ::insert_value( rnBorder, mnRightColor, 27, 5 );
1638 #endif
1640 void XclExpCellBorder::FillToXF5( sal_uInt32& rnBorder, sal_uInt32& rnArea ) const
1642 ::insert_value( rnBorder, mnTopLine, 0, 3 );
1643 ::insert_value( rnBorder, mnLeftLine, 3, 3 );
1644 ::insert_value( rnArea, mnBottomLine, 22, 3 );
1645 ::insert_value( rnBorder, mnRightLine, 6, 3 );
1646 ::insert_value( rnBorder, mnTopColor, 9, 7 );
1647 ::insert_value( rnBorder, mnLeftColor, 16, 7 );
1648 ::insert_value( rnArea, mnBottomColor, 25, 7 );
1649 ::insert_value( rnBorder, mnRightColor, 23, 7 );
1652 void XclExpCellBorder::FillToXF8( sal_uInt32& rnBorder1, sal_uInt32& rnBorder2 ) const
1654 ::insert_value( rnBorder1, mnLeftLine, 0, 4 );
1655 ::insert_value( rnBorder1, mnRightLine, 4, 4 );
1656 ::insert_value( rnBorder1, mnTopLine, 8, 4 );
1657 ::insert_value( rnBorder1, mnBottomLine, 12, 4 );
1658 ::insert_value( rnBorder1, mnLeftColor, 16, 7 );
1659 ::insert_value( rnBorder1, mnRightColor, 23, 7 );
1660 ::insert_value( rnBorder2, mnTopColor, 0, 7 );
1661 ::insert_value( rnBorder2, mnBottomColor, 7, 7 );
1662 ::insert_value( rnBorder2, mnDiagColor, 14, 7 );
1663 ::insert_value( rnBorder2, mnDiagLine, 21, 4 );
1664 ::set_flag( rnBorder1, EXC_XF_DIAGONAL_TL_TO_BR, mbDiagTLtoBR );
1665 ::set_flag( rnBorder1, EXC_XF_DIAGONAL_BL_TO_TR, mbDiagBLtoTR );
1668 void XclExpCellBorder::FillToCF8( sal_uInt16& rnLine, sal_uInt32& rnColor ) const
1670 ::insert_value( rnLine, mnLeftLine, 0, 4 );
1671 ::insert_value( rnLine, mnRightLine, 4, 4 );
1672 ::insert_value( rnLine, mnTopLine, 8, 4 );
1673 ::insert_value( rnLine, mnBottomLine, 12, 4 );
1674 ::insert_value( rnColor, mnLeftColor, 0, 7 );
1675 ::insert_value( rnColor, mnRightColor, 7, 7 );
1676 ::insert_value( rnColor, mnTopColor, 16, 7 );
1677 ::insert_value( rnColor, mnBottomColor, 23, 7 );
1680 static const char* ToLineStyle( sal_uInt8 nLineStyle )
1682 switch( nLineStyle )
1684 case EXC_LINE_NONE: return "none";
1685 case EXC_LINE_THIN: return "thin";
1686 case EXC_LINE_MEDIUM: return "medium";
1687 case EXC_LINE_THICK: return "thick";
1688 case EXC_LINE_DOUBLE: return "double";
1689 case EXC_LINE_HAIR: return "hair";
1691 return "*unknown*";
1694 static void lcl_WriteBorder( XclExpXmlStream& rStrm, sal_Int32 nElement, sal_uInt8 nLineStyle, const Color& rColor )
1696 sax_fastparser::FSHelperPtr& rStyleSheet = rStrm.GetCurrentStream();
1697 if( nLineStyle == EXC_LINE_NONE )
1698 rStyleSheet->singleElement( nElement, FSEND );
1699 else if( rColor == Color( 0, 0, 0, 0 ) )
1700 rStyleSheet->singleElement( nElement,
1701 XML_style, ToLineStyle( nLineStyle ),
1702 FSEND );
1703 else
1705 rStyleSheet->startElement( nElement,
1706 XML_style, ToLineStyle( nLineStyle ),
1707 FSEND );
1708 rStyleSheet->singleElement( XML_color,
1709 XML_rgb, XclXmlUtils::ToOString( rColor ).getStr(),
1710 FSEND );
1711 rStyleSheet->endElement( nElement );
1715 void XclExpCellBorder::SaveXml( XclExpXmlStream& rStrm ) const
1717 sax_fastparser::FSHelperPtr& rStyleSheet = rStrm.GetCurrentStream();
1719 XclExpPalette& rPalette = rStrm.GetRoot().GetPalette();
1721 rStyleSheet->startElement( XML_border,
1722 XML_diagonalUp, XclXmlUtils::ToPsz( mbDiagBLtoTR ),
1723 XML_diagonalDown, XclXmlUtils::ToPsz( mbDiagTLtoBR ),
1724 // OOXTODO: XML_outline,
1725 FSEND );
1726 lcl_WriteBorder( rStrm, XML_left, mnLeftLine, rPalette.GetColor( mnLeftColor ) );
1727 lcl_WriteBorder( rStrm, XML_right, mnRightLine, rPalette.GetColor( mnRightColor ) );
1728 lcl_WriteBorder( rStrm, XML_top, mnTopLine, rPalette.GetColor( mnTopColor ) );
1729 lcl_WriteBorder( rStrm, XML_bottom, mnBottomLine, rPalette.GetColor( mnBottomColor ) );
1730 lcl_WriteBorder( rStrm, XML_diagonal, mnDiagLine, rPalette.GetColor( mnDiagColor ) );
1731 // OOXTODO: XML_vertical, XML_horizontal
1732 rStyleSheet->endElement( XML_border );
1735 // ----------------------------------------------------------------------------
1737 XclExpCellArea::XclExpCellArea() :
1738 mnForeColorId( XclExpPalette::GetColorIdFromIndex( mnForeColor ) ),
1739 mnBackColorId( XclExpPalette::GetColorIdFromIndex( mnBackColor ) )
1743 bool XclExpCellArea::FillFromItemSet( const SfxItemSet& rItemSet, XclExpPalette& rPalette, bool bStyle )
1745 const SvxBrushItem& rBrushItem = GETITEM( rItemSet, SvxBrushItem, ATTR_BACKGROUND );
1746 if( rBrushItem.GetColor().GetTransparency() )
1748 mnPattern = EXC_PATT_NONE;
1749 mnForeColorId = XclExpPalette::GetColorIdFromIndex( EXC_COLOR_WINDOWTEXT );
1750 mnBackColorId = XclExpPalette::GetColorIdFromIndex( EXC_COLOR_WINDOWBACK );
1752 else
1754 mnPattern = EXC_PATT_SOLID;
1755 mnForeColorId = rPalette.InsertColor( rBrushItem.GetColor(), EXC_COLOR_CELLAREA );
1756 mnBackColorId = XclExpPalette::GetColorIdFromIndex( EXC_COLOR_WINDOWTEXT );
1758 return ScfTools::CheckItem( rItemSet, ATTR_BACKGROUND, bStyle );
1761 void XclExpCellArea::SetFinalColors( const XclExpPalette& rPalette )
1763 rPalette.GetMixedColors( mnForeColor, mnBackColor, mnPattern, mnForeColorId, mnBackColorId );
1766 #if 0
1767 void XclExpCellArea::FillToXF2( sal_uInt8& rnFlags ) const
1769 ::set_flag( rnFlags, EXC_XF2_BACKGROUND, mnPattern != EXC_PATT_NONE );
1772 void XclExpCellArea::FillToXF3( sal_uInt16& rnArea ) const
1774 ::insert_value( rnArea, mnPattern, 0, 6 );
1775 ::insert_value( rnArea, mnForeColor, 6, 5 );
1776 ::insert_value( rnArea, mnBackColor, 11, 5 );
1778 #endif
1780 void XclExpCellArea::FillToXF5( sal_uInt32& rnArea ) const
1782 ::insert_value( rnArea, mnPattern, 16, 6 );
1783 ::insert_value( rnArea, mnForeColor, 0, 7 );
1784 ::insert_value( rnArea, mnBackColor, 7, 7 );
1787 void XclExpCellArea::FillToXF8( sal_uInt32& rnBorder2, sal_uInt16& rnArea ) const
1789 ::insert_value( rnBorder2, mnPattern, 26, 6 );
1790 ::insert_value( rnArea, mnForeColor, 0, 7 );
1791 ::insert_value( rnArea, mnBackColor, 7, 7 );
1794 void XclExpCellArea::FillToCF8( sal_uInt16& rnPattern, sal_uInt16& rnColor ) const
1796 XclCellArea aTmp( *this );
1797 if( !aTmp.IsTransparent() && (aTmp.mnBackColor == EXC_COLOR_WINDOWTEXT) )
1798 aTmp.mnBackColor = 0;
1799 if( aTmp.mnPattern == EXC_PATT_SOLID )
1800 ::std::swap( aTmp.mnForeColor, aTmp.mnBackColor );
1801 ::insert_value( rnColor, aTmp.mnForeColor, 0, 7 );
1802 ::insert_value( rnColor, aTmp.mnBackColor, 7, 7 );
1803 ::insert_value( rnPattern, aTmp.mnPattern, 10, 6 );
1806 static const char* ToPatternType( sal_uInt8 nPattern )
1808 switch( nPattern )
1810 case EXC_PATT_NONE: return "none";
1811 case EXC_PATT_SOLID: return "solid";
1812 case EXC_PATT_50_PERC: return "mediumGray";
1813 case EXC_PATT_75_PERC: return "darkGray";
1814 case EXC_PATT_25_PERC: return "lightGray";
1815 case EXC_PATT_12_5_PERC: return "gray125";
1816 case EXC_PATT_6_25_PERC: return "gray0625";
1818 return "*unknown*";
1821 void XclExpCellArea::SaveXml( XclExpXmlStream& rStrm ) const
1823 sax_fastparser::FSHelperPtr& rStyleSheet = rStrm.GetCurrentStream();
1824 rStyleSheet->startElement( XML_fill,
1825 FSEND );
1827 // OOXTODO: XML_gradientFill
1829 XclExpPalette& rPalette = rStrm.GetRoot().GetPalette();
1831 if( mnPattern == EXC_PATT_NONE || ( mnForeColor == 0 && mnBackColor == 0 ) )
1832 rStyleSheet->singleElement( XML_patternFill,
1833 XML_patternType, ToPatternType( mnPattern ),
1834 FSEND );
1835 else
1837 rStyleSheet->startElement( XML_patternFill,
1838 XML_patternType, ToPatternType( mnPattern ),
1839 FSEND );
1840 rStyleSheet->singleElement( XML_fgColor,
1841 XML_rgb, XclXmlUtils::ToOString( rPalette.GetColor( mnForeColor ) ).getStr(),
1842 FSEND );
1843 rStyleSheet->singleElement( XML_bgColor,
1844 XML_rgb, XclXmlUtils::ToOString( rPalette.GetColor( mnBackColor ) ).getStr(),
1845 FSEND );
1846 rStyleSheet->endElement( XML_patternFill );
1849 rStyleSheet->endElement( XML_fill );
1852 // ----------------------------------------------------------------------------
1854 XclExpXFId::XclExpXFId() :
1855 mnXFId( XclExpXFBuffer::GetDefCellXFId() ),
1856 mnXFIndex( EXC_XF_DEFAULTCELL )
1860 XclExpXFId::XclExpXFId( sal_uInt32 nXFId ) :
1861 mnXFId( nXFId ),
1862 mnXFIndex( EXC_XF_DEFAULTCELL )
1866 void XclExpXFId::ConvertXFIndex( const XclExpRoot& rRoot )
1868 mnXFIndex = rRoot.GetXFBuffer().GetXFIndex( mnXFId );
1871 // ----------------------------------------------------------------------------
1873 XclExpXF::XclExpXF(
1874 const XclExpRoot& rRoot, const ScPatternAttr& rPattern, sal_Int16 nScript,
1875 ULONG nForceScNumFmt, sal_uInt16 nForceXclFont, bool bForceLineBreak ) :
1876 XclXFBase( true ),
1877 XclExpRoot( rRoot )
1879 mnParentXFId = GetXFBuffer().InsertStyle( rPattern.GetStyleSheet() );
1880 Init( rPattern.GetItemSet(), nScript, nForceScNumFmt, nForceXclFont, bForceLineBreak, false );
1883 XclExpXF::XclExpXF( const XclExpRoot& rRoot, const SfxStyleSheetBase& rStyleSheet ) :
1884 XclXFBase( false ),
1885 XclExpRoot( rRoot ),
1886 mnParentXFId( XclExpXFBuffer::GetXFIdFromIndex( EXC_XF_STYLEPARENT ) )
1888 bool bDefStyle = (rStyleSheet.GetName() == ScGlobal::GetRscString( STR_STYLENAME_STANDARD ));
1889 Init( const_cast< SfxStyleSheetBase& >( rStyleSheet ).GetItemSet(), ::com::sun::star::i18n::ScriptType::WEAK,
1890 NUMBERFORMAT_ENTRY_NOT_FOUND, EXC_FONT_NOTFOUND, false, bDefStyle );
1893 XclExpXF::XclExpXF( const XclExpRoot& rRoot, bool bCellXF ) :
1894 XclXFBase( bCellXF ),
1895 XclExpRoot( rRoot ),
1896 mnParentXFId( XclExpXFBuffer::GetXFIdFromIndex( EXC_XF_STYLEPARENT ) )
1898 InitDefault();
1901 bool XclExpXF::Equals( const ScPatternAttr& rPattern,
1902 ULONG nForceScNumFmt, sal_uInt16 nForceXclFont, bool bForceLineBreak ) const
1904 return IsCellXF() && (mpItemSet == &rPattern.GetItemSet()) &&
1905 (!bForceLineBreak || maAlignment.mbLineBreak) &&
1906 ((nForceScNumFmt == NUMBERFORMAT_ENTRY_NOT_FOUND) || (mnScNumFmt == nForceScNumFmt)) &&
1907 ((nForceXclFont == EXC_FONT_NOTFOUND) || (mnXclFont == nForceXclFont));
1910 bool XclExpXF::Equals( const SfxStyleSheetBase& rStyleSheet ) const
1912 return IsStyleXF() && (mpItemSet == &const_cast< SfxStyleSheetBase& >( rStyleSheet ).GetItemSet());
1915 void XclExpXF::SetFinalColors()
1917 maBorder.SetFinalColors( GetPalette() );
1918 maArea.SetFinalColors( GetPalette() );
1921 bool XclExpXF::Equals( const XclExpXF& rCmpXF ) const
1923 return XclXFBase::Equals( rCmpXF ) &&
1924 (maProtection == rCmpXF.maProtection) && (maAlignment == rCmpXF.maAlignment) &&
1925 (maBorder == rCmpXF.maBorder) && (maArea == rCmpXF.maArea) &&
1926 (mnXclFont == rCmpXF.mnXclFont) && (mnXclNumFmt == rCmpXF.mnXclNumFmt) &&
1927 (mnParentXFId == rCmpXF.mnParentXFId);
1930 void XclExpXF::InitDefault()
1932 SetRecHeader( EXC_ID5_XF, (GetBiff() == EXC_BIFF8) ? 20 : 16 );
1933 mpItemSet = 0;
1934 mnScNumFmt = NUMBERFORMAT_ENTRY_NOT_FOUND;
1935 mnXclFont = mnXclNumFmt = 0;
1938 void XclExpXF::Init( const SfxItemSet& rItemSet, sal_Int16 nScript,
1939 ULONG nForceScNumFmt, sal_uInt16 nForceXclFont, bool bForceLineBreak, bool bDefStyle )
1941 InitDefault();
1942 mpItemSet = &rItemSet;
1944 // cell protection
1945 mbProtUsed = maProtection.FillFromItemSet( rItemSet, IsStyleXF() );
1947 // font
1948 if( nForceXclFont == EXC_FONT_NOTFOUND )
1950 mnXclFont = GetFontBuffer().Insert( rItemSet, nScript, EXC_COLOR_CELLTEXT, bDefStyle );
1951 mbFontUsed = XclExpFontBuffer::CheckItems( rItemSet, nScript, IsStyleXF() );
1953 else
1955 mnXclFont = nForceXclFont;
1956 mbFontUsed = true;
1959 // number format
1960 mnScNumFmt = (nForceScNumFmt == NUMBERFORMAT_ENTRY_NOT_FOUND) ?
1961 GETITEMVALUE( rItemSet, SfxUInt32Item, ATTR_VALUE_FORMAT, ULONG ) : nForceScNumFmt;
1962 mnXclNumFmt = GetNumFmtBuffer().Insert( mnScNumFmt );
1963 mbFmtUsed = ScfTools::CheckItem( rItemSet, ATTR_VALUE_FORMAT, IsStyleXF() );
1965 // alignment
1966 mbAlignUsed = maAlignment.FillFromItemSet( rItemSet, bForceLineBreak, GetBiff(), IsStyleXF() );
1968 // cell border
1969 mbBorderUsed = maBorder.FillFromItemSet( rItemSet, GetPalette(), GetBiff(), IsStyleXF() );
1971 // background area
1972 mbAreaUsed = maArea.FillFromItemSet( rItemSet, GetPalette(), IsStyleXF() );
1974 // set all b***Used flags to true in "Default"/"Normal" style
1975 if( bDefStyle )
1976 SetAllUsedFlags( true );
1979 sal_uInt8 XclExpXF::GetUsedFlags() const
1981 sal_uInt8 nUsedFlags = 0;
1982 /* In cell XFs a set bit means a used attribute, in style XFs a cleared bit.
1983 "mbCellXF == mb***Used" evaluates to correct value in cell and style XFs. */
1984 ::set_flag( nUsedFlags, EXC_XF_DIFF_PROT, mbCellXF == mbProtUsed );
1985 ::set_flag( nUsedFlags, EXC_XF_DIFF_FONT, mbCellXF == mbFontUsed );
1986 ::set_flag( nUsedFlags, EXC_XF_DIFF_VALFMT, mbCellXF == mbFmtUsed );
1987 ::set_flag( nUsedFlags, EXC_XF_DIFF_ALIGN, mbCellXF == mbAlignUsed );
1988 ::set_flag( nUsedFlags, EXC_XF_DIFF_BORDER, mbCellXF == mbBorderUsed );
1989 ::set_flag( nUsedFlags, EXC_XF_DIFF_AREA, mbCellXF == mbAreaUsed );
1990 return nUsedFlags;
1993 void XclExpXF::WriteBody5( XclExpStream& rStrm )
1995 sal_uInt16 nTypeProt = 0, nAlign = 0;
1996 sal_uInt32 nArea = 0, nBorder = 0;
1998 ::set_flag( nTypeProt, EXC_XF_STYLE, IsStyleXF() );
1999 ::insert_value( nTypeProt, mnParent, 4, 12 );
2000 ::insert_value( nAlign, GetUsedFlags(), 10, 6 );
2002 maProtection.FillToXF3( nTypeProt );
2003 maAlignment.FillToXF5( nAlign );
2004 maBorder.FillToXF5( nBorder, nArea );
2005 maArea.FillToXF5( nArea );
2007 rStrm << mnXclFont << mnXclNumFmt << nTypeProt << nAlign << nArea << nBorder;
2010 void XclExpXF::WriteBody8( XclExpStream& rStrm )
2012 sal_uInt16 nTypeProt = 0, nAlign = 0, nMiscAttrib = 0, nArea = 0;
2013 sal_uInt32 nBorder1 = 0, nBorder2 = 0;
2015 ::set_flag( nTypeProt, EXC_XF_STYLE, IsStyleXF() );
2016 ::insert_value( nTypeProt, mnParent, 4, 12 );
2017 ::insert_value( nMiscAttrib, GetUsedFlags(), 10, 6 );
2019 maProtection.FillToXF3( nTypeProt );
2020 maAlignment.FillToXF8( nAlign, nMiscAttrib );
2021 maBorder.FillToXF8( nBorder1, nBorder2 );
2022 maArea.FillToXF8( nBorder2, nArea );
2024 rStrm << mnXclFont << mnXclNumFmt << nTypeProt << nAlign << nMiscAttrib << nBorder1 << nBorder2 << nArea;
2027 void XclExpXF::WriteBody( XclExpStream& rStrm )
2029 XclExpXFId aParentId( mnParentXFId );
2030 aParentId.ConvertXFIndex( GetRoot() );
2031 mnParent = aParentId.mnXFIndex;
2032 switch( GetBiff() )
2034 case EXC_BIFF5: WriteBody5( rStrm ); break;
2035 case EXC_BIFF8: WriteBody8( rStrm ); break;
2036 default: DBG_ERROR_BIFF();
2040 void XclExpXF::SetXmlIds( sal_uInt32 nBorderId, sal_uInt32 nFillId )
2042 mnBorderId = nBorderId;
2043 mnFillId = nFillId;
2046 void XclExpXF::SaveXml( XclExpXmlStream& rStrm )
2048 sax_fastparser::FSHelperPtr& rStyleSheet = rStrm.GetCurrentStream();
2050 sal_Int32 nXfId = 0;
2051 if( IsCellXF() )
2053 sal_uInt16 nXFIndex = rStrm.GetRoot().GetXFBuffer().GetXFIndex( mnParentXFId );
2054 nXfId = rStrm.GetRoot().GetXFBuffer().GetXmlStyleIndex( nXFIndex );
2057 rStyleSheet->startElement( XML_xf,
2058 XML_numFmtId, OString::valueOf( (sal_Int32) mnXclNumFmt ).getStr(),
2059 XML_fontId, OString::valueOf( (sal_Int32) mnXclFont ).getStr(),
2060 XML_fillId, OString::valueOf( (sal_Int32) mnFillId ).getStr(),
2061 XML_borderId, OString::valueOf( (sal_Int32) mnBorderId ).getStr(),
2062 XML_xfId, IsStyleXF() ? NULL : OString::valueOf( nXfId ).getStr(),
2063 // OOXTODO: XML_quotePrefix,
2064 // OOXTODO: XML_pivotButton,
2065 // OOXTODO: XML_applyNumberFormat, ;
2066 XML_applyFont, XclXmlUtils::ToPsz( mbFontUsed ),
2067 // OOXTODO: XML_applyFill,
2068 XML_applyBorder, XclXmlUtils::ToPsz( mbBorderUsed ),
2069 XML_applyAlignment, XclXmlUtils::ToPsz( mbAlignUsed ),
2070 XML_applyProtection, XclXmlUtils::ToPsz( mbProtUsed ),
2071 FSEND );
2072 if( mbAlignUsed )
2073 maAlignment.SaveXml( rStrm );
2074 if( mbProtUsed )
2075 maProtection.SaveXml( rStrm );
2076 // OOXTODO: XML_extLst
2077 rStyleSheet->endElement( XML_xf );
2080 // ----------------------------------------------------------------------------
2082 XclExpDefaultXF::XclExpDefaultXF( const XclExpRoot& rRoot, bool bCellXF ) :
2083 XclExpXF( rRoot, bCellXF )
2087 //UNUSED2008-05 void XclExpDefaultXF::SetParent( sal_uInt32 nParentXFId )
2088 //UNUSED2008-05 {
2089 //UNUSED2008-05 DBG_ASSERT( IsCellXF(), "XclExpDefaultXF::SetParent - not allowed in style XFs" );
2090 //UNUSED2008-05 if( IsCellXF() )
2091 //UNUSED2008-05 mnParentXFId = nParentXFId;
2092 //UNUSED2008-05 }
2093 //UNUSED2008-05
2094 //UNUSED2008-05 void XclExpDefaultXF::SetUsedFlags(
2095 //UNUSED2008-05 bool bProtUsed, bool bFontUsed, bool bFmtUsed,
2096 //UNUSED2008-05 bool bAlignUsed, bool bBorderUsed, bool bAreaUsed )
2097 //UNUSED2008-05 {
2098 //UNUSED2008-05 mbProtUsed = bProtUsed;
2099 //UNUSED2008-05 mbFontUsed = bFontUsed;
2100 //UNUSED2008-05 mbFmtUsed = bFmtUsed;
2101 //UNUSED2008-05 mbAlignUsed = bAlignUsed;
2102 //UNUSED2008-05 mbBorderUsed = bBorderUsed;
2103 //UNUSED2008-05 mbAreaUsed = bAreaUsed;
2104 //UNUSED2008-05 }
2105 //UNUSED2008-05
2106 //UNUSED2008-05 void XclExpDefaultXF::SetProtection( const XclExpCellProt& rProtection )
2107 //UNUSED2008-05 {
2108 //UNUSED2008-05 maProtection = rProtection;
2109 //UNUSED2008-05 mbProtUsed = true;
2110 //UNUSED2008-05 }
2111 //UNUSED2008-05
2112 //UNUSED2008-05 void XclExpDefaultXF::SetAlignment( const XclExpCellAlign& rAlignment )
2113 //UNUSED2008-05 {
2114 //UNUSED2008-05 maAlignment = rAlignment;
2115 //UNUSED2008-05 mbAlignUsed = true;
2116 //UNUSED2008-05 }
2117 //UNUSED2008-05
2118 //UNUSED2008-05 void XclExpDefaultXF::SetBorder( const XclExpCellBorder& rBorder )
2119 //UNUSED2008-05 {
2120 //UNUSED2008-05 maBorder = rBorder;
2121 //UNUSED2008-05 mbBorderUsed = true;
2122 //UNUSED2008-05 }
2123 //UNUSED2008-05
2124 //UNUSED2008-05 void XclExpDefaultXF::SetArea( const XclExpCellArea& rArea )
2125 //UNUSED2008-05 {
2126 //UNUSED2008-05 maArea = rArea;
2127 //UNUSED2008-05 mbAreaUsed = true;
2128 //UNUSED2008-05 }
2130 void XclExpDefaultXF::SetFont( sal_uInt16 nXclFont )
2132 mnXclFont = nXclFont;
2133 mbFontUsed = true;
2136 void XclExpDefaultXF::SetNumFmt( sal_uInt16 nXclNumFmt )
2138 mnXclNumFmt = nXclNumFmt;
2139 mbFmtUsed = true;
2142 // ----------------------------------------------------------------------------
2144 XclExpStyle::XclExpStyle( sal_uInt32 nXFId, const String& rStyleName ) :
2145 XclExpRecord( EXC_ID_STYLE, 4 ),
2146 maName( rStyleName ),
2147 maXFId( nXFId ),
2148 mnStyleId( EXC_STYLE_USERDEF ),
2149 mnLevel( EXC_STYLE_NOLEVEL )
2151 DBG_ASSERT( maName.Len(), "XclExpStyle::XclExpStyle - empty style name" );
2152 #ifdef DBG_UTIL
2153 sal_uInt8 nStyleId, nLevel; // do not use members for debug tests
2154 DBG_ASSERT( !XclTools::GetBuiltInStyleId( nStyleId, nLevel, maName ),
2155 "XclExpStyle::XclExpStyle - this is a built-in style" );
2156 #endif
2159 XclExpStyle::XclExpStyle( sal_uInt32 nXFId, sal_uInt8 nStyleId, sal_uInt8 nLevel ) :
2160 XclExpRecord( EXC_ID_STYLE, 4 ),
2161 maXFId( nXFId ),
2162 mnStyleId( nStyleId ),
2163 mnLevel( nLevel )
2167 void XclExpStyle::WriteBody( XclExpStream& rStrm )
2169 maXFId.ConvertXFIndex( rStrm.GetRoot() );
2170 ::set_flag( maXFId.mnXFIndex, EXC_STYLE_BUILTIN, IsBuiltIn() );
2171 rStrm << maXFId.mnXFIndex;
2173 if( IsBuiltIn() )
2175 rStrm << mnStyleId << mnLevel;
2177 else
2179 XclExpString aNameEx;
2180 if( rStrm.GetRoot().GetBiff() == EXC_BIFF8 )
2181 aNameEx.Assign( maName );
2182 else
2183 aNameEx.AssignByte( maName, rStrm.GetRoot().GetTextEncoding(), EXC_STR_8BITLENGTH );
2184 rStrm << aNameEx;
2188 static const char* lcl_StyleNameFromId( sal_Int32 nStyleId )
2190 switch( nStyleId )
2192 case 0: return "Normal";
2193 case 3: return "Comma";
2194 case 4: return "Currency";
2195 case 5: return "Percent";
2196 case 6: return "Comma [0]";
2197 case 7: return "Currency [0]";
2199 return "*unknown*";
2202 void XclExpStyle::SaveXml( XclExpXmlStream& rStrm )
2204 OString sName;
2205 if( IsBuiltIn() )
2207 sName = OString( lcl_StyleNameFromId( mnStyleId ) );
2209 else
2210 sName = XclXmlUtils::ToOString( maName );
2211 sal_Int32 nXFId = rStrm.GetRoot().GetXFBuffer().GetXmlStyleIndex( maXFId.mnXFId );
2212 rStrm.GetCurrentStream()->singleElement( XML_cellStyle,
2213 XML_name, sName.getStr(),
2214 XML_xfId, OString::valueOf( nXFId ).getStr(),
2215 XML_builtinId, OString::valueOf( (sal_Int32) mnStyleId ).getStr(),
2216 // OOXTODO: XML_iLevel,
2217 // OOXTODO: XML_hidden,
2218 XML_customBuiltin, XclXmlUtils::ToPsz( ! IsBuiltIn() ),
2219 FSEND );
2220 // OOXTODO: XML_extLst
2223 // ----------------------------------------------------------------------------
2225 namespace {
2227 const sal_uInt32 EXC_XFLIST_INDEXBASE = 0xFFFE0000;
2228 /** Maximum count of XF records to store in the XF list (performance). */
2229 const sal_uInt32 EXC_XFLIST_HARDLIMIT = 256 * 1024;
2231 bool lclIsBuiltInStyle( const String& rStyleName )
2233 return
2234 XclTools::IsBuiltInStyleName( rStyleName ) ||
2235 XclTools::IsCondFormatStyleName( rStyleName );
2238 } // namespace
2240 // ----------------------------------------------------------------------------
2242 XclExpXFBuffer::XclExpBuiltInInfo::XclExpBuiltInInfo() :
2243 mnStyleId( EXC_STYLE_USERDEF ),
2244 mnLevel( EXC_STYLE_NOLEVEL ),
2245 mbPredefined( true ),
2246 mbHasStyleRec( false )
2250 // ----------------------------------------------------------------------------
2252 /** Predicate for search algorithm. */
2253 struct XclExpBorderPred
2255 const XclExpCellBorder&
2256 mrBorder;
2257 inline explicit XclExpBorderPred( const XclExpCellBorder& rBorder ) : mrBorder( rBorder ) {}
2258 bool operator()( const XclExpCellBorder& rBorder ) const;
2261 bool XclExpBorderPred::operator()( const XclExpCellBorder& rBorder ) const
2263 return
2264 mrBorder.mnLeftColor == rBorder.mnLeftColor &&
2265 mrBorder.mnRightColor == rBorder.mnRightColor &&
2266 mrBorder.mnTopColor == rBorder.mnTopColor &&
2267 mrBorder.mnBottomColor == rBorder.mnBottomColor &&
2268 mrBorder.mnDiagColor == rBorder.mnDiagColor &&
2269 mrBorder.mnLeftLine == rBorder.mnLeftLine &&
2270 mrBorder.mnRightLine == rBorder.mnRightLine &&
2271 mrBorder.mnTopLine == rBorder.mnTopLine &&
2272 mrBorder.mnBottomLine == rBorder.mnBottomLine &&
2273 mrBorder.mnDiagLine == rBorder.mnDiagLine &&
2274 mrBorder.mbDiagTLtoBR == rBorder.mbDiagTLtoBR &&
2275 mrBorder.mbDiagBLtoTR == rBorder.mbDiagBLtoTR &&
2276 mrBorder.mnLeftColorId == rBorder.mnLeftColorId &&
2277 mrBorder.mnRightColorId == rBorder.mnRightColorId &&
2278 mrBorder.mnTopColorId == rBorder.mnTopColorId &&
2279 mrBorder.mnBottomColorId == rBorder.mnBottomColorId &&
2280 mrBorder.mnDiagColorId == rBorder.mnDiagColorId;
2283 struct XclExpFillPred
2285 const XclExpCellArea&
2286 mrFill;
2287 inline explicit XclExpFillPred( const XclExpCellArea& rFill ) : mrFill( rFill ) {}
2288 bool operator()( const XclExpCellArea& rFill ) const;
2291 bool XclExpFillPred::operator()( const XclExpCellArea& rFill ) const
2293 return
2294 mrFill.mnForeColor == rFill.mnForeColor &&
2295 mrFill.mnBackColor == rFill.mnBackColor &&
2296 mrFill.mnPattern == rFill.mnPattern &&
2297 mrFill.mnForeColorId == rFill.mnForeColorId &&
2298 mrFill.mnBackColorId == rFill.mnBackColorId;
2301 XclExpXFBuffer::XclExpXFBuffer( const XclExpRoot& rRoot ) :
2302 XclExpRoot( rRoot )
2306 void XclExpXFBuffer::Initialize()
2308 InsertDefaultRecords();
2309 InsertUserStyles();
2312 sal_uInt32 XclExpXFBuffer::Insert( const ScPatternAttr* pPattern, sal_Int16 nScript )
2314 return InsertCellXF( pPattern, nScript, NUMBERFORMAT_ENTRY_NOT_FOUND, EXC_FONT_NOTFOUND, false );
2317 sal_uInt32 XclExpXFBuffer::InsertWithFont( const ScPatternAttr* pPattern, sal_Int16 nScript,
2318 sal_uInt16 nForceXclFont, bool bForceLineBreak )
2320 return InsertCellXF( pPattern, nScript, NUMBERFORMAT_ENTRY_NOT_FOUND, nForceXclFont, bForceLineBreak );
2323 sal_uInt32 XclExpXFBuffer::InsertWithNumFmt( const ScPatternAttr* pPattern, sal_Int16 nScript, ULONG nForceScNumFmt, bool bForceLineBreak )
2325 return InsertCellXF( pPattern, nScript, nForceScNumFmt, EXC_FONT_NOTFOUND, bForceLineBreak );
2328 sal_uInt32 XclExpXFBuffer::InsertStyle( const SfxStyleSheetBase* pStyleSheet )
2330 return pStyleSheet ? InsertStyleXF( *pStyleSheet ) : GetXFIdFromIndex( EXC_XF_DEFAULTSTYLE );
2333 sal_uInt32 XclExpXFBuffer::GetXFIdFromIndex( sal_uInt16 nXFIndex )
2335 return EXC_XFLIST_INDEXBASE | nXFIndex;
2338 sal_uInt32 XclExpXFBuffer::GetDefCellXFId()
2340 return GetXFIdFromIndex( EXC_XF_DEFAULTCELL );
2343 const XclExpXF* XclExpXFBuffer::GetXFById( sal_uInt32 nXFId ) const
2345 return maXFList.GetRecord( nXFId ).get();
2348 void XclExpXFBuffer::Finalize()
2350 for( size_t nPos = 0, nSize = maXFList.GetSize(); nPos < nSize; ++nPos )
2351 maXFList.GetRecord( nPos )->SetFinalColors();
2353 sal_uInt32 nTotalCount = static_cast< sal_uInt32 >( maXFList.GetSize() );
2354 sal_uInt32 nId;
2355 maXFIndexVec.resize( nTotalCount, EXC_XF_DEFAULTCELL );
2356 maStyleIndexes.resize( nTotalCount, EXC_XF_DEFAULTCELL );
2357 maCellIndexes.resize( nTotalCount, EXC_XF_DEFAULTCELL );
2359 XclExpBuiltInMap::const_iterator aBuiltInEnd = maBuiltInMap.end();
2360 /* nMaxBuiltInXFId used to decide faster whether an XF record is
2361 user-defined. If the current XF ID is greater than this value,
2362 maBuiltInMap doesn't need to be searched. */
2363 sal_uInt32 nMaxBuiltInXFId = maBuiltInMap.empty() ? 0 : maBuiltInMap.rbegin()->first;
2365 // *** map all built-in XF records (cell and style) *** -------------------
2367 // do not change XF order -> std::map<> iterates elements in ascending order
2368 for( XclExpBuiltInMap::const_iterator aIt = maBuiltInMap.begin(); aIt != aBuiltInEnd; ++aIt )
2369 AppendXFIndex( aIt->first );
2371 // *** insert all user-defined style XF records, without reduce *** -------
2373 sal_uInt32 nStyleXFCount = 0; // counts up to EXC_XF_MAXSTYLECOUNT limit
2375 for( nId = 0; nId < nTotalCount; ++nId )
2377 XclExpXFRef xXF = maXFList.GetRecord( nId );
2378 if( xXF->IsStyleXF() && ((nId > nMaxBuiltInXFId) || (maBuiltInMap.find( nId ) == aBuiltInEnd)) )
2380 if( nStyleXFCount < EXC_XF_MAXSTYLECOUNT )
2382 // maximum count of styles not reached
2383 AppendXFIndex( nId );
2384 ++nStyleXFCount;
2386 else
2388 /* Maximum count of styles reached - do not append more
2389 pointers to XFs; use default style XF instead; do not break
2390 the loop to initialize all maXFIndexVec elements. */
2391 maXFIndexVec[ nId ] = EXC_XF_DEFAULTSTYLE;
2396 // *** insert all cell XF records *** -------------------------------------
2398 // start position to search for equal inserted XF records
2399 size_t nSearchStart = maSortedXFList.GetSize();
2401 // break the loop if XF limit reached - maXFIndexVec is already initialized with default index
2402 XclExpXFRef xDefCellXF = maXFList.GetRecord( EXC_XF_DEFAULTCELL );
2403 for( nId = 0; (nId < nTotalCount) && (maSortedXFList.GetSize() < EXC_XF_MAXCOUNT); ++nId )
2405 XclExpXFRef xXF = maXFList.GetRecord( nId );
2406 if( xXF->IsCellXF() && ((nId > nMaxBuiltInXFId) || (maBuiltInMap.find( nId ) == aBuiltInEnd)) )
2408 // try to find an XF record equal to *xXF, which is already inserted
2409 sal_uInt16 nFoundIndex = EXC_XF_NOTFOUND;
2411 // first try if it is equal to the default cell XF
2412 if( xDefCellXF->Equals( *xXF ) )
2414 nFoundIndex = EXC_XF_DEFAULTCELL;
2416 else for( size_t nSearchPos = nSearchStart, nSearchEnd = maSortedXFList.GetSize();
2417 (nSearchPos < nSearchEnd) && (nFoundIndex == EXC_XF_NOTFOUND); ++nSearchPos )
2419 if( maSortedXFList.GetRecord( nSearchPos )->Equals( *xXF ) )
2420 nFoundIndex = static_cast< sal_uInt16 >( nSearchPos );
2423 if( nFoundIndex != EXC_XF_NOTFOUND )
2424 // equal XF already in the list, use its resulting XF index
2425 maXFIndexVec[ nId ] = nFoundIndex;
2426 else
2427 AppendXFIndex( nId );
2431 sal_uInt16 nXmlStyleIndex = 0;
2432 sal_uInt16 nXmlCellIndex = 0;
2434 size_t nXFCount = maSortedXFList.GetSize();
2435 for( size_t i = 0; i < nXFCount; ++i )
2437 XclExpXFList::RecordRefType xXF = maSortedXFList.GetRecord( i );
2438 if( xXF->IsStyleXF() )
2439 maStyleIndexes[ i ] = nXmlStyleIndex++;
2440 else
2441 maCellIndexes[ i ] = nXmlCellIndex++;
2445 sal_uInt16 XclExpXFBuffer::GetXFIndex( sal_uInt32 nXFId ) const
2447 sal_uInt16 nXFIndex = EXC_XF_DEFAULTSTYLE;
2448 if( nXFId >= EXC_XFLIST_INDEXBASE )
2449 nXFIndex = static_cast< sal_uInt16 >( nXFId & ~EXC_XFLIST_INDEXBASE );
2450 else if( nXFId < maXFIndexVec.size() )
2451 nXFIndex = maXFIndexVec[ nXFId ];
2452 return nXFIndex;
2455 sal_Int32 XclExpXFBuffer::GetXmlStyleIndex( sal_uInt32 nXFIndex ) const
2457 DBG_ASSERT( nXFIndex < maStyleIndexes.size(), "XclExpXFBuffer::GetXmlStyleIndex - invalid index!" );
2458 if( nXFIndex > maStyleIndexes.size() )
2459 return 0; // should be caught/debugged via above assert; return "valid" index.
2460 return maStyleIndexes[ nXFIndex ];
2463 sal_Int32 XclExpXFBuffer::GetXmlCellIndex( sal_uInt32 nXFIndex ) const
2465 DBG_ASSERT( nXFIndex < maCellIndexes.size(), "XclExpXFBuffer::GetXmlStyleIndex - invalid index!" );
2466 if( nXFIndex > maCellIndexes.size() )
2467 return 0; // should be caught/debugged via above assert; return "valid" index.
2468 return maCellIndexes[ nXFIndex ];
2471 void XclExpXFBuffer::Save( XclExpStream& rStrm )
2473 // save all XF records contained in the maSortedXFList vector (sorted by XF index)
2474 maSortedXFList.Save( rStrm );
2475 // save all STYLE records
2476 maStyleList.Save( rStrm );
2479 static void lcl_GetCellCounts( const XclExpRecordList< XclExpXF >& rXFList, sal_Int32& rCells, sal_Int32& rStyles )
2481 rCells = 0;
2482 rStyles = 0;
2483 size_t nXFCount = rXFList.GetSize();
2484 for( size_t i = 0; i < nXFCount; ++i )
2486 XclExpRecordList< XclExpXF >::RecordRefType xXF = rXFList.GetRecord( i );
2487 if( xXF->IsCellXF() )
2488 ++rCells;
2489 else if( xXF->IsStyleXF() )
2490 ++rStyles;
2494 void XclExpXFBuffer::SaveXml( XclExpXmlStream& rStrm )
2496 sax_fastparser::FSHelperPtr& rStyleSheet = rStrm.GetCurrentStream();
2498 rStyleSheet->startElement( XML_fills,
2499 XML_count, OString::valueOf( (sal_Int32) maFills.size() ).getStr(),
2500 FSEND );
2501 for( XclExpFillList::iterator aIt = maFills.begin(), aEnd = maFills.end();
2502 aIt != aEnd; ++aIt )
2504 aIt->SaveXml( rStrm );
2506 rStyleSheet->endElement( XML_fills );
2508 rStyleSheet->startElement( XML_borders,
2509 XML_count, OString::valueOf( (sal_Int32) maBorders.size() ).getStr(),
2510 FSEND );
2511 for( XclExpBorderList::iterator aIt = maBorders.begin(), aEnd = maBorders.end();
2512 aIt != aEnd; ++aIt )
2514 aIt->SaveXml( rStrm );
2516 rStyleSheet->endElement( XML_borders );
2518 // save all XF records contained in the maSortedXFList vector (sorted by XF index)
2519 sal_Int32 nCells, nStyles;
2520 lcl_GetCellCounts( maSortedXFList, nCells, nStyles );
2522 if( nStyles > 0 )
2524 rStyleSheet->startElement( XML_cellStyleXfs,
2525 XML_count, OString::valueOf( nStyles ).getStr(),
2526 FSEND );
2527 size_t nXFCount = maSortedXFList.GetSize();
2528 for( size_t i = 0; i < nXFCount; ++i )
2530 XclExpXFList::RecordRefType xXF = maSortedXFList.GetRecord( i );
2531 if( ! xXF->IsStyleXF() )
2532 continue;
2533 SaveXFXml( rStrm, *xXF );
2535 rStyleSheet->endElement( XML_cellStyleXfs );
2538 if( nCells > 0 )
2540 rStyleSheet->startElement( XML_cellXfs,
2541 XML_count, OString::valueOf( nCells ).getStr(),
2542 FSEND );
2543 size_t nXFCount = maSortedXFList.GetSize();
2544 for( size_t i = 0; i < nXFCount; ++i )
2546 XclExpXFList::RecordRefType xXF = maSortedXFList.GetRecord( i );
2547 if( ! xXF->IsCellXF() )
2548 continue;
2549 SaveXFXml( rStrm, *xXF );
2551 rStyleSheet->endElement( XML_cellXfs );
2554 // save all STYLE records
2555 rStyleSheet->startElement( XML_cellStyles,
2556 XML_count, OString::valueOf( (sal_Int32) maStyleList.GetSize() ).getStr(),
2557 FSEND );
2558 maStyleList.SaveXml( rStrm );
2559 rStyleSheet->endElement( XML_cellStyles );
2562 void XclExpXFBuffer::SaveXFXml( XclExpXmlStream& rStrm, XclExpXF& rXF )
2564 XclExpBorderList::iterator aBorderPos =
2565 std::find_if( maBorders.begin(), maBorders.end(), XclExpBorderPred( rXF.GetBorderData() ) );
2566 DBG_ASSERT( aBorderPos != maBorders.end(), "XclExpXFBuffer::SaveXml - Invalid @borderId!" );
2567 XclExpFillList::iterator aFillPos =
2568 std::find_if( maFills.begin(), maFills.end(), XclExpFillPred( rXF.GetAreaData() ) );
2569 DBG_ASSERT( aFillPos != maFills.end(), "XclExpXFBuffer::SaveXml - Invalid @fillId!" );
2571 sal_Int32 nBorderId = 0, nFillId = 0;
2572 if( aBorderPos != maBorders.end() )
2573 nBorderId = std::distance( maBorders.begin(), aBorderPos );
2574 if( aFillPos != maFills.end() )
2575 nFillId = std::distance( maFills.begin(), aFillPos );
2577 rXF.SetXmlIds( nBorderId, nFillId );
2578 rXF.SaveXml( rStrm );
2581 sal_uInt32 XclExpXFBuffer::FindXF( const ScPatternAttr& rPattern,
2582 ULONG nForceScNumFmt, sal_uInt16 nForceXclFont, bool bForceLineBreak ) const
2584 for( size_t nPos = 0, nSize = maXFList.GetSize(); nPos < nSize; ++nPos )
2585 if( maXFList.GetRecord( nPos )->Equals( rPattern, nForceScNumFmt, nForceXclFont, bForceLineBreak ) )
2586 return static_cast< sal_uInt32 >( nPos );
2587 return EXC_XFID_NOTFOUND;
2590 sal_uInt32 XclExpXFBuffer::FindXF( const SfxStyleSheetBase& rStyleSheet ) const
2592 for( size_t nPos = 0, nSize = maXFList.GetSize(); nPos < nSize; ++nPos )
2593 if( maXFList.GetRecord( nPos )->Equals( rStyleSheet ) )
2594 return static_cast< sal_uInt32 >( nPos );
2595 return EXC_XFID_NOTFOUND;
2598 sal_uInt32 XclExpXFBuffer::FindBuiltInXF( sal_uInt8 nStyleId, sal_uInt8 nLevel ) const
2600 for( XclExpBuiltInMap::const_iterator aIt = maBuiltInMap.begin(), aEnd = maBuiltInMap.end(); aIt != aEnd; ++aIt )
2601 if( (aIt->second.mnStyleId == nStyleId) && (aIt->second.mnLevel == nLevel) )
2602 return aIt->first;
2603 return EXC_XFID_NOTFOUND;
2606 sal_uInt32 XclExpXFBuffer::InsertCellXF( const ScPatternAttr* pPattern, sal_Int16 nScript,
2607 ULONG nForceScNumFmt, sal_uInt16 nForceXclFont, bool bForceLineBreak )
2609 const ScPatternAttr* pDefPattern = GetDoc().GetDefPattern();
2610 if( !pPattern )
2611 pPattern = pDefPattern;
2613 // special handling for default cell formatting
2614 if( (pPattern == pDefPattern) && !bForceLineBreak &&
2615 (nForceScNumFmt == NUMBERFORMAT_ENTRY_NOT_FOUND) &&
2616 (nForceXclFont == EXC_FONT_NOTFOUND) )
2618 // Is it the first try to insert the default cell format?
2619 bool& rbPredefined = maBuiltInMap[ EXC_XF_DEFAULTCELL ].mbPredefined;
2620 if( rbPredefined )
2622 // replace default cell pattern
2623 XclExpXFRef xNewXF( new XclExpXF( GetRoot(), *pPattern, nScript ) );
2624 maXFList.ReplaceRecord( xNewXF, EXC_XF_DEFAULTCELL );
2625 rbPredefined = false;
2627 return GetDefCellXFId();
2630 sal_uInt32 nXFId = FindXF( *pPattern, nForceScNumFmt, nForceXclFont, bForceLineBreak );
2631 if( nXFId == EXC_XFID_NOTFOUND )
2633 // not found - insert new cell XF
2634 if( maXFList.GetSize() < EXC_XFLIST_HARDLIMIT )
2636 maXFList.AppendNewRecord( new XclExpXF(
2637 GetRoot(), *pPattern, nScript, nForceScNumFmt, nForceXclFont, bForceLineBreak ) );
2638 // do not set nXFId before the AppendNewRecord() call - it may insert 2 XFs (style+cell)
2639 nXFId = static_cast< sal_uInt32 >( maXFList.GetSize() - 1 );
2641 else
2643 // list full - fall back to default cell XF
2644 nXFId = GetDefCellXFId();
2647 return nXFId;
2650 sal_uInt32 XclExpXFBuffer::InsertStyleXF( const SfxStyleSheetBase& rStyleSheet )
2652 // *** try, if it is a built-in style - create new XF or replace existing predefined XF ***
2654 sal_uInt8 nStyleId, nLevel;
2655 if( XclTools::GetBuiltInStyleId( nStyleId, nLevel, rStyleSheet.GetName() ) )
2657 // try to find the built-in XF record (if already created in InsertDefaultRecords())
2658 sal_uInt32 nXFId = FindBuiltInXF( nStyleId, nLevel );
2659 if( nXFId == EXC_XFID_NOTFOUND )
2661 // built-in style XF not yet created - do it now
2662 XclExpXFRef xXF( new XclExpXF( GetRoot(), rStyleSheet ) );
2663 nXFId = AppendBuiltInXFWithStyle( xXF, nStyleId, nLevel );
2664 // this new XF record is not predefined
2665 maBuiltInMap[ nXFId ].mbPredefined = false;
2667 else
2669 DBG_ASSERT( maXFList.HasRecord( nXFId ), "XclExpXFBuffer::InsertStyleXF - built-in XF not found" );
2670 // XF record still predefined? -> Replace with real XF
2671 bool& rbPredefined = maBuiltInMap[ nXFId ].mbPredefined;
2672 if( rbPredefined )
2674 // replace predefined built-in style (ReplaceRecord() deletes old record)
2675 maXFList.ReplaceRecord( XclExpXFRef( new XclExpXF( GetRoot(), rStyleSheet ) ), nXFId );
2676 rbPredefined = false;
2680 // STYLE already inserted? (may be not, i.e. for RowLevel/ColLevel or Hyperlink styles)
2681 bool& rbHasStyleRec = maBuiltInMap[ nXFId ].mbHasStyleRec;
2682 if( !rbHasStyleRec )
2684 maStyleList.AppendNewRecord( new XclExpStyle( nXFId, nStyleId, nLevel ) );
2685 rbHasStyleRec = true;
2688 return nXFId;
2691 // *** try to find the XF record of a user-defined style ***
2693 sal_uInt32 nXFId = FindXF( rStyleSheet );
2694 if( nXFId == EXC_XFID_NOTFOUND )
2696 // not found - insert new style XF and STYLE
2697 nXFId = static_cast< sal_uInt32 >( maXFList.GetSize() );
2698 if( nXFId < EXC_XFLIST_HARDLIMIT )
2700 maXFList.AppendNewRecord( new XclExpXF( GetRoot(), rStyleSheet ) );
2701 // create the STYLE record
2702 if( rStyleSheet.GetName().Len() )
2703 maStyleList.AppendNewRecord( new XclExpStyle( nXFId, rStyleSheet.GetName() ) );
2705 else
2706 // list full - fall back to default style XF
2707 nXFId = GetXFIdFromIndex( EXC_XF_DEFAULTSTYLE );
2709 return nXFId;
2712 void XclExpXFBuffer::InsertUserStyles()
2714 SfxStyleSheetIterator aStyleIter( GetDoc().GetStyleSheetPool(), SFX_STYLE_FAMILY_PARA );
2715 for( SfxStyleSheetBase* pStyleSheet = aStyleIter.First(); pStyleSheet; pStyleSheet = aStyleIter.Next() )
2716 if( pStyleSheet->IsUserDefined() && !lclIsBuiltInStyle( pStyleSheet->GetName() ) )
2717 InsertStyleXF( *pStyleSheet );
2720 sal_uInt32 XclExpXFBuffer::AppendBuiltInXF( XclExpXFRef xXF, sal_uInt8 nStyleId, sal_uInt8 nLevel )
2722 sal_uInt32 nXFId = static_cast< sal_uInt32 >( maXFList.GetSize() );
2723 maXFList.AppendRecord( xXF );
2724 XclExpBuiltInInfo& rInfo = maBuiltInMap[ nXFId ];
2725 rInfo.mnStyleId = nStyleId;
2726 rInfo.mnLevel = nLevel;
2727 rInfo.mbPredefined = true;
2728 return nXFId;
2731 sal_uInt32 XclExpXFBuffer::AppendBuiltInXFWithStyle( XclExpXFRef xXF, sal_uInt8 nStyleId, sal_uInt8 nLevel )
2733 sal_uInt32 nXFId = AppendBuiltInXF( xXF, nStyleId, nLevel );
2734 maStyleList.AppendNewRecord( new XclExpStyle( nXFId, nStyleId, nLevel ) );
2735 maBuiltInMap[ nXFId ].mbHasStyleRec = true; // mark existing STYLE record
2736 return nXFId;
2739 static XclExpCellArea lcl_GetPatternFill_None()
2741 XclExpCellArea aFill;
2742 aFill.mnPattern = EXC_PATT_NONE;
2743 return aFill;
2746 static XclExpCellArea lcl_GetPatternFill_Gray125()
2748 XclExpCellArea aFill;
2749 aFill.mnPattern = EXC_PATT_12_5_PERC;
2750 aFill.mnForeColor = 0;
2751 aFill.mnBackColor = 0;
2752 return aFill;
2755 void XclExpXFBuffer::InsertDefaultRecords()
2757 maFills.push_back( lcl_GetPatternFill_None() );
2758 maFills.push_back( lcl_GetPatternFill_Gray125() );
2760 // index 0: default style
2761 if( SfxStyleSheetBase* pDefStyleSheet = GetStyleSheetPool().Find( ScGlobal::GetRscString( STR_STYLENAME_STANDARD ), SFX_STYLE_FAMILY_PARA ) )
2763 XclExpXFRef xDefStyle( new XclExpXF( GetRoot(), *pDefStyleSheet ) );
2764 sal_uInt32 nXFId = AppendBuiltInXFWithStyle( xDefStyle, EXC_STYLE_NORMAL );
2765 // mark this XF as not predefined, prevents overwriting
2766 maBuiltInMap[ nXFId ].mbPredefined = false;
2768 else
2770 DBG_ERRORFILE( "XclExpXFBuffer::InsertDefaultRecords - default style not found" );
2771 XclExpXFRef xDefStyle( new XclExpDefaultXF( GetRoot(), false ) );
2772 xDefStyle->SetAllUsedFlags( true );
2773 AppendBuiltInXFWithStyle( xDefStyle, EXC_STYLE_NORMAL );
2776 // index 1-14: RowLevel and ColLevel styles (without STYLE records)
2777 XclExpDefaultXF aLevelStyle( GetRoot(), false );
2778 // RowLevel_1, ColLevel_1
2779 aLevelStyle.SetFont( 1 );
2780 AppendBuiltInXF( XclExpXFRef( new XclExpDefaultXF( aLevelStyle ) ), EXC_STYLE_ROWLEVEL, 0 );
2781 AppendBuiltInXF( XclExpXFRef( new XclExpDefaultXF( aLevelStyle ) ), EXC_STYLE_COLLEVEL, 0 );
2782 // RowLevel_2, ColLevel_2
2783 aLevelStyle.SetFont( 2 );
2784 AppendBuiltInXF( XclExpXFRef( new XclExpDefaultXF( aLevelStyle ) ), EXC_STYLE_ROWLEVEL, 1 );
2785 AppendBuiltInXF( XclExpXFRef( new XclExpDefaultXF( aLevelStyle ) ), EXC_STYLE_COLLEVEL, 1 );
2786 // RowLevel_3, ColLevel_3 ... RowLevel_7, ColLevel_7
2787 aLevelStyle.SetFont( 0 );
2788 for( sal_uInt8 nLevel = 2; nLevel < EXC_STYLE_LEVELCOUNT; ++nLevel )
2790 AppendBuiltInXF( XclExpXFRef( new XclExpDefaultXF( aLevelStyle ) ), EXC_STYLE_ROWLEVEL, nLevel );
2791 AppendBuiltInXF( XclExpXFRef( new XclExpDefaultXF( aLevelStyle ) ), EXC_STYLE_COLLEVEL, nLevel );
2794 // index 15: default hard cell format, placeholder to be able to add more built-in styles
2795 maXFList.AppendNewRecord( new XclExpDefaultXF( GetRoot(), true ) );
2796 maBuiltInMap[ EXC_XF_DEFAULTCELL ].mbPredefined = true;
2798 // index 16-20: other built-in styles
2799 XclExpDefaultXF aFormatStyle( GetRoot(), false );
2800 aFormatStyle.SetFont( 1 );
2801 aFormatStyle.SetNumFmt( 43 );
2802 AppendBuiltInXFWithStyle( XclExpXFRef( new XclExpDefaultXF( aFormatStyle ) ), EXC_STYLE_COMMA );
2803 aFormatStyle.SetNumFmt( 41 );
2804 AppendBuiltInXFWithStyle( XclExpXFRef( new XclExpDefaultXF( aFormatStyle ) ), EXC_STYLE_COMMA_0 );
2805 aFormatStyle.SetNumFmt( 44 );
2806 AppendBuiltInXFWithStyle( XclExpXFRef( new XclExpDefaultXF( aFormatStyle ) ), EXC_STYLE_CURRENCY );
2807 aFormatStyle.SetNumFmt( 42 );
2808 AppendBuiltInXFWithStyle( XclExpXFRef( new XclExpDefaultXF( aFormatStyle ) ), EXC_STYLE_CURRENCY_0 );
2809 aFormatStyle.SetNumFmt( 9 );
2810 AppendBuiltInXFWithStyle( XclExpXFRef( new XclExpDefaultXF( aFormatStyle ) ), EXC_STYLE_PERCENT );
2812 // other built-in style XF records (i.e. Hyperlink styles) are created on demand
2814 /* Insert the real default hard cell format -> 0 is document default pattern.
2815 Do it here (and not already above) to really have all built-in styles. */
2816 Insert( 0, GetDefApiScript() );
2819 void XclExpXFBuffer::AppendXFIndex( sal_uInt32 nXFId )
2821 DBG_ASSERT( nXFId < maXFIndexVec.size(), "XclExpXFBuffer::AppendXFIndex - XF ID out of range" );
2822 maXFIndexVec[ nXFId ] = static_cast< sal_uInt16 >( maSortedXFList.GetSize() );
2823 XclExpXFRef xXF = maXFList.GetRecord( nXFId );
2824 AddBorderAndFill( *xXF );
2825 maSortedXFList.AppendRecord( xXF );
2826 DBG_ASSERT( maXFList.HasRecord( nXFId ), "XclExpXFBuffer::AppendXFIndex - XF not found" );
2829 void XclExpXFBuffer::AddBorderAndFill( const XclExpXF& rXF )
2831 if( std::find_if( maBorders.begin(), maBorders.end(), XclExpBorderPred( rXF.GetBorderData() ) ) == maBorders.end() )
2833 maBorders.push_back( rXF.GetBorderData() );
2836 if( std::find_if( maFills.begin(), maFills.end(), XclExpFillPred( rXF.GetAreaData() ) ) == maFills.end() )
2838 maFills.push_back( rXF.GetAreaData() );
2842 // ============================================================================
2844 XclExpXmlStyleSheet::XclExpXmlStyleSheet( const XclExpRoot& rRoot )
2845 : XclExpRoot( rRoot )
2849 void XclExpXmlStyleSheet::SaveXml( XclExpXmlStream& rStrm )
2851 sax_fastparser::FSHelperPtr aStyleSheet = rStrm.CreateOutputStream(
2852 OUString::createFromAscii( "xl/styles.xml" ),
2853 OUString::createFromAscii( "styles.xml" ),
2854 rStrm.GetCurrentStream()->getOutputStream(),
2855 "application/vnd.openxmlformats-officedocument.spreadsheetml.styles+xml",
2856 "http://schemas.openxmlformats.org/officeDocument/2006/relationships/styles" );
2857 rStrm.PushStream( aStyleSheet );
2859 aStyleSheet->startElement( XML_styleSheet,
2860 XML_xmlns, "http://schemas.openxmlformats.org/spreadsheetml/2006/main",
2861 FSEND );
2863 CreateRecord( EXC_ID_FORMATLIST )->SaveXml( rStrm );
2864 CreateRecord( EXC_ID_FONTLIST )->SaveXml( rStrm );
2865 CreateRecord( EXC_ID_XFLIST )->SaveXml( rStrm );
2866 CreateRecord( EXC_ID_PALETTE )->SaveXml( rStrm );
2868 aStyleSheet->endElement( XML_styleSheet );
2870 rStrm.PopStream();
2873 // ============================================================================