1 /**************************************************************
2 *
3 * Licensed to the Apache Software Foundation (ASF) under one
4 * or more contributor license agreements. See the NOTICE file
5 * distributed with this work for additional information
6 * regarding copyright ownership. The ASF licenses this file
7 * to you under the Apache License, Version 2.0 (the
8 * "License"); you may not use this file except in compliance
9 * with the License. You may obtain a copy of the License at
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing,
14 * software distributed under the License is distributed on an
15 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16 * KIND, either express or implied. See the License for the
17 * specific language governing permissions and limitations
18 * under the License.
19 *
20 *************************************************************/
21
22
23
24 // MARKER(update_precomp.py): autogen include statement, do not remove
25 #include "precompiled_scfilt.hxx"
26 #include "xestyle.hxx"
27
28 #include <algorithm>
29 #include <iterator>
30 #include <set>
31 #include <com/sun/star/i18n/ScriptType.hpp>
32 #include <vcl/font.hxx>
33 #include <svl/zformat.hxx>
34 #include <svl/languageoptions.hxx>
35 #include <sfx2/printer.hxx>
36 #include "scitems.hxx"
37 #include <svx/algitem.hxx>
38 #include <editeng/boxitem.hxx>
39 #include <editeng/bolnitem.hxx>
40 #include <svx/rotmodit.hxx>
41 #include <editeng/colritem.hxx>
42 #include <editeng/brshitem.hxx>
43 #include <editeng/frmdiritem.hxx>
44 #include <editeng/eeitem.hxx>
45 #include <editeng/escpitem.hxx>
46 #include "document.hxx"
47 #include "stlpool.hxx"
48 #include "stlsheet.hxx"
49 #include "patattr.hxx"
50 #include "attrib.hxx"
51 #include "globstr.hrc"
52 #include "xestring.hxx"
53
54 using namespace ::oox;
55
56 using ::rtl::OString;
57 using ::rtl::OUString;
58
59 // PALETTE record - color information =========================================
60
61 namespace {
62
lclGetWeighting(XclExpColorType eType)63 sal_uInt32 lclGetWeighting( XclExpColorType eType )
64 {
65 switch( eType )
66 {
67 case EXC_COLOR_CHARTLINE: return 1;
68 case EXC_COLOR_CELLBORDER:
69 case EXC_COLOR_CHARTAREA: return 2;
70 case EXC_COLOR_CELLTEXT:
71 case EXC_COLOR_CHARTTEXT:
72 case EXC_COLOR_CTRLTEXT: return 10;
73 case EXC_COLOR_TABBG:
74 case EXC_COLOR_CELLAREA: return 20;
75 case EXC_COLOR_GRID: return 50;
76 default: DBG_ERRORFILE( "lclGetWeighting - unknown color type" );
77 }
78 return 1;
79 }
80
lclGetColorDistance(const Color & rColor1,const Color & rColor2)81 sal_Int32 lclGetColorDistance( const Color& rColor1, const Color& rColor2 )
82 {
83 sal_Int32 nDist = rColor1.GetRed() - rColor2.GetRed();
84 nDist *= nDist * 77;
85 sal_Int32 nDummy = rColor1.GetGreen() - rColor2.GetGreen();
86 nDist += nDummy * nDummy * 151;
87 nDummy = rColor1.GetBlue() - rColor2.GetBlue();
88 nDist += nDummy * nDummy * 28;
89 return nDist;
90 }
91
lclGetMergedColorComp(sal_uInt8 nComp1,sal_uInt32 nWeight1,sal_uInt8 nComp2,sal_uInt32 nWeight2)92 sal_uInt8 lclGetMergedColorComp( sal_uInt8 nComp1, sal_uInt32 nWeight1, sal_uInt8 nComp2, sal_uInt32 nWeight2 )
93 {
94 sal_uInt8 nComp1Dist = ::std::min< sal_uInt8 >( nComp1, 0xFF - nComp1 );
95 sal_uInt8 nComp2Dist = ::std::min< sal_uInt8 >( nComp2, 0xFF - nComp2 );
96 if( nComp1Dist != nComp2Dist )
97 {
98 /* #i36945# One of the passed RGB components is nearer at the limits (0x00 or 0xFF).
99 Increase its weighting to prevent fading of the colors during reduction. */
100 const sal_uInt8& rnCompNearer = (nComp1Dist < nComp2Dist) ? nComp1 : nComp2;
101 sal_uInt32& rnWeight = (nComp1Dist < nComp2Dist) ? nWeight1 : nWeight2;
102 rnWeight *= ((rnCompNearer - 0x80L) * (rnCompNearer - 0x7FL) / 0x1000L + 1);
103 }
104 sal_uInt32 nWSum = nWeight1 + nWeight2;
105 return static_cast< sal_uInt8 >( (nComp1 * nWeight1 + nComp2 * nWeight2 + nWSum / 2) / nWSum );
106 }
107
lclSetMixedColor(Color & rDest,const Color & rSrc1,const Color & rSrc2)108 void lclSetMixedColor( Color& rDest, const Color& rSrc1, const Color& rSrc2 )
109 {
110 rDest.SetRed( static_cast< sal_uInt8 >( (static_cast< sal_uInt16 >( rSrc1.GetRed() ) + rSrc2.GetRed()) / 2 ) );
111 rDest.SetGreen( static_cast< sal_uInt8 >( (static_cast< sal_uInt16 >( rSrc1.GetGreen() ) + rSrc2.GetGreen()) / 2 ) );
112 rDest.SetBlue( static_cast< sal_uInt8 >( (static_cast< sal_uInt16 >( rSrc1.GetBlue() ) + rSrc2.GetBlue()) / 2 ) );
113 }
114
115 } // namespace
116
117 // additional classes for color reduction -------------------------------------
118
119 namespace {
120
121 /** Represents an entry in a color list.
122
123 The color stores a weighting value, which increases the more the color is
124 used in the document. Heavy-weighted colors will change less than others on
125 color reduction.
126 */
127 class XclListColor
128 {
129 DECL_FIXEDMEMPOOL_NEWDEL( XclListColor )
130
131 private:
132 Color maColor; /// The color value of this palette entry.
133 sal_uInt32 mnColorId; /// Unique color ID for color reduction.
134 sal_uInt32 mnWeight; /// Weighting for color reduction.
135 bool mbBaseColor; /// true = Handle as base color, (don't remove/merge).
136
137 public:
138 explicit XclListColor( const Color& rColor, sal_uInt32 nColorId );
139
140 /** Returns the RGB color value of the color. */
GetColor() const141 inline const Color& GetColor() const { return maColor; }
142 /** Returns the unique ID of the color. */
GetColorId() const143 inline sal_uInt32 GetColorId() const { return mnColorId; }
144 /** Returns the current weighting of the color. */
GetWeighting() const145 inline sal_uInt32 GetWeighting() const { return mnWeight; }
146 /** Returns true, if this color is a base color, i.e. it will not be removed or merged. */
IsBaseColor() const147 inline bool IsBaseColor() const { return mbBaseColor; }
148
149 /** Adds the passed weighting to this color. */
AddWeighting(sal_uInt32 nWeight)150 inline void AddWeighting( sal_uInt32 nWeight ) { mnWeight += nWeight; }
151 /** Merges this color with rColor, regarding weighting settings. */
152 void Merge( const XclListColor& rColor );
153 };
154
155 IMPL_FIXEDMEMPOOL_NEWDEL( XclListColor, 100, 100 )
156
XclListColor(const Color & rColor,sal_uInt32 nColorId)157 XclListColor::XclListColor( const Color& rColor, sal_uInt32 nColorId ) :
158 maColor( rColor ),
159 mnColorId( nColorId ),
160 mnWeight( 0 )
161 {
162 mbBaseColor =
163 ((rColor.GetRed() == 0x00) || (rColor.GetRed() == 0xFF)) &&
164 ((rColor.GetGreen() == 0x00) || (rColor.GetGreen() == 0xFF)) &&
165 ((rColor.GetBlue() == 0x00) || (rColor.GetBlue() == 0xFF));
166 }
167
Merge(const XclListColor & rColor)168 void XclListColor::Merge( const XclListColor& rColor )
169 {
170 sal_uInt32 nWeight2 = rColor.GetWeighting();
171 // do not change RGB value of base colors
172 if( !mbBaseColor )
173 {
174 maColor.SetRed( lclGetMergedColorComp( maColor.GetRed(), mnWeight, rColor.maColor.GetRed(), nWeight2 ) );
175 maColor.SetGreen( lclGetMergedColorComp( maColor.GetGreen(), mnWeight, rColor.maColor.GetGreen(), nWeight2 ) );
176 maColor.SetBlue( lclGetMergedColorComp( maColor.GetBlue(), mnWeight, rColor.maColor.GetBlue(), nWeight2 ) );
177 }
178 AddWeighting( nWeight2 );
179 }
180
181 // ----------------------------------------------------------------------------
182
183 /** Data for each inserted original color, represented by a color ID. */
184 struct XclColorIdData
185 {
186 Color maColor; /// The original inserted color.
187 sal_uInt32 mnIndex; /// Maps current color ID to color list or export color vector.
188 /** Sets the contents of this struct. */
Set__anon953b9b800211::XclColorIdData189 inline void Set( const Color& rColor, sal_uInt32 nIndex ) { maColor = rColor; mnIndex = nIndex; }
190 };
191
192 /** A color that will be written to the Excel file. */
193 struct XclPaletteColor
194 {
195 Color maColor; /// Resulting color to export.
196 bool mbUsed; /// true = Entry is used in the document.
197
XclPaletteColor__anon953b9b800211::XclPaletteColor198 inline explicit XclPaletteColor( const Color& rColor ) : maColor( rColor ), mbUsed( false ) {}
SetColor__anon953b9b800211::XclPaletteColor199 inline void SetColor( const Color& rColor ) { maColor = rColor; mbUsed = true; }
200 };
201
202 /** Maps a color list index to a palette index.
203 @descr Used to remap the color ID data vector from list indexes to palette indexes. */
204 struct XclRemap
205 {
206 sal_uInt32 mnPalIndex; /// Index to palette.
207 bool mbProcessed; /// true = List color already processed.
208
XclRemap__anon953b9b800211::XclRemap209 inline explicit XclRemap() : mnPalIndex( 0 ), mbProcessed( false ) {}
SetIndex__anon953b9b800211::XclRemap210 inline void SetIndex( sal_uInt32 nPalIndex )
211 { mnPalIndex = nPalIndex; mbProcessed = true; }
212 };
213
214 /** Stores the nearest palette color index of a list color. */
215 struct XclNearest
216 {
217 sal_uInt32 mnPalIndex; /// Index to nearest palette color.
218 sal_Int32 mnDist; /// Distance to palette color.
219
XclNearest__anon953b9b800211::XclNearest220 inline explicit XclNearest() : mnPalIndex( 0 ), mnDist( 0 ) {}
221 };
222
223 typedef ::std::vector< XclRemap > XclRemapVec;
224 typedef ::std::vector< XclNearest > XclNearestVec;
225
226 } // namespace
227
228 // ----------------------------------------------------------------------------
229
230 class XclExpPaletteImpl
231 {
232 public:
233 explicit XclExpPaletteImpl( const XclDefaultPalette& rDefPal );
234
235 /** Inserts the color into the list and updates weighting.
236 @param nAutoDefault The Excel palette index for automatic color.
237 @return A unique ID for this color. */
238 sal_uInt32 InsertColor( const Color& rColor, XclExpColorType eType, sal_uInt16 nAutoDefault = 0 );
239 /** Returns the color ID representing a fixed Excel palette index (i.e. for auto colors). */
240 static sal_uInt32 GetColorIdFromIndex( sal_uInt16 nIndex );
241
242 /** Reduces the color list to the maximum count of the current BIFF version. */
243 void Finalize();
244
245 /** Returns the Excel palette index of the color with passed color ID. */
246 sal_uInt16 GetColorIndex( sal_uInt32 nColorId ) const;
247
248 /** Returns a foreground and background color for the two passed color IDs.
249 @descr If rnXclPattern contains a solid pattern, this function tries to find
250 the two best fitting colors and a mix pattern (25%, 50% or 75%) for nForeColorId.
251 This will result in a better approximation to the passed foreground color. */
252 void GetMixedColors(
253 sal_uInt16& rnXclForeIx, sal_uInt16& rnXclBackIx, sal_uInt8& rnXclPattern,
254 sal_uInt32 nForeColorId, sal_uInt32 nBackColorId ) const;
255
256 /** Returns the RGB color data for a (non-zero-based) Excel palette entry.
257 @return The color from current or default palette or COL_AUTO, if nothing else found. */
258 ColorData GetColorData( sal_uInt16 nXclIndex ) const;
259 /** Returns the color for a (non-zero-based) Excel palette entry.
260 @return The color from current or default palette or COL_AUTO, if nothing else found. */
GetColor(sal_uInt16 nXclIndex) const261 inline Color GetColor( sal_uInt16 nXclIndex ) const
262 { return Color( GetColorData( nXclIndex ) ); }
263
264 /** Returns true, if all colors of the palette are equal to default palette colors. */
265 bool IsDefaultPalette() const;
266 /** Writes the color list (contents of the palette record) to the passed stream. */
267 void WriteBody( XclExpStream& rStrm );
268 void SaveXml( XclExpXmlStream& rStrm );
269
270 private:
271 /** Returns the Excel index of a 0-based color index. */
GetXclIndex(sal_uInt32 nIndex) const272 inline sal_uInt16 GetXclIndex( sal_uInt32 nIndex ) const
273 { return static_cast< sal_uInt16 >( nIndex + EXC_COLOR_USEROFFSET ); }
274
275 /** Returns the original inserted color represented by the color ID nColorId. */
276 const Color& GetOriginalColor( sal_uInt32 nColorId ) const;
277
278 /** Searches for rColor, returns the ordered insertion index for rColor in rnIndex. */
279 XclListColor* SearchListEntry( const Color& rColor, sal_uInt32& rnIndex );
280 /** Creates and inserts a new color list entry at the specified list position. */
281 XclListColor* CreateListEntry( const Color& rColor, sal_uInt32 nIndex );
282
283 /** Raw and fast reduction of the palette. */
284 void RawReducePalette( sal_uInt32 nPass );
285 /** Reduction of one color using advanced color merging based on color weighting. */
286 void ReduceLeastUsedColor();
287
288 /** Finds the least used color and returns its current list index. */
289 sal_uInt32 GetLeastUsedListColor() const;
290 /** Returns the list index of the color nearest to rColor.
291 @param nIgnore List index of a color which will be ignored.
292 @return The list index of the found color. */
293 sal_uInt32 GetNearestListColor( const Color& rColor, sal_uInt32 nIgnore ) const;
294 /** Returns the list index of the color nearest to the color with list index nIndex. */
295 sal_uInt32 GetNearestListColor( sal_uInt32 nIndex ) const;
296
297 /** Returns in rnIndex the palette index of the color nearest to rColor.
298 @param bDefaultOnly true = Searches for default colors only (colors never replaced).
299 @return The distance from passed color to found color. */
300 sal_Int32 GetNearestPaletteColor(
301 sal_uInt32& rnIndex,
302 const Color& rColor, bool bDefaultOnly ) const;
303 /** Returns in rnFirst and rnSecond the palette indexes of the two colors nearest to rColor.
304 @return The minimum distance from passed color to found colors. */
305 sal_Int32 GetNearPaletteColors(
306 sal_uInt32& rnFirst, sal_uInt32& rnSecond,
307 const Color& rColor ) const;
308
309 private:
310 typedef ScfDelList< XclListColor > XclListColorList;
311 typedef ScfRef< XclListColorList > XclListColorListRef;
312 typedef ::std::vector< XclColorIdData > XclColorIdDataVec;
313 typedef ::std::vector< XclPaletteColor > XclPaletteColorVec;
314
315 const XclDefaultPalette& mrDefPal; /// The default palette for the current BIFF version.
316 XclListColorListRef mxColorList; /// Working color list.
317 XclColorIdDataVec maColorIdDataVec; /// Data of all CIDs.
318 XclPaletteColorVec maPalette; /// Contains resulting colors to export.
319 sal_uInt32 mnLastIdx; /// Last insertion index for search opt.
320 };
321
322 // ----------------------------------------------------------------------------
323
324 const sal_uInt32 EXC_PAL_INDEXBASE = 0xFFFF0000;
325 const sal_uInt32 EXC_PAL_MAXRAWSIZE = 1024;
326
XclExpPaletteImpl(const XclDefaultPalette & rDefPal)327 XclExpPaletteImpl::XclExpPaletteImpl( const XclDefaultPalette& rDefPal ) :
328 mrDefPal( rDefPal ),
329 mxColorList( new XclListColorList ),
330 mnLastIdx( 0 )
331 {
332 // initialize maPalette with default colors
333 sal_uInt16 nCount = static_cast< sal_uInt16 >( mrDefPal.GetColorCount() );
334 maPalette.reserve( nCount );
335 for( sal_uInt16 nIdx = 0; nIdx < nCount; ++nIdx )
336 maPalette.push_back( XclPaletteColor( mrDefPal.GetDefColor( GetXclIndex( nIdx ) ) ) );
337
338 InsertColor( Color( COL_BLACK ), EXC_COLOR_CELLTEXT );
339 }
340
InsertColor(const Color & rColor,XclExpColorType eType,sal_uInt16 nAutoDefault)341 sal_uInt32 XclExpPaletteImpl::InsertColor( const Color& rColor, XclExpColorType eType, sal_uInt16 nAutoDefault )
342 {
343 if( rColor.GetColor() == COL_AUTO )
344 return GetColorIdFromIndex( nAutoDefault );
345
346 sal_uInt32 nFoundIdx = 0;
347 XclListColor* pEntry = SearchListEntry( rColor, nFoundIdx );
348 if( !pEntry || (pEntry->GetColor() != rColor) )
349 pEntry = CreateListEntry( rColor, nFoundIdx );
350 pEntry->AddWeighting( lclGetWeighting( eType ) );
351
352 return pEntry->GetColorId();
353 }
354
GetColorIdFromIndex(sal_uInt16 nIndex)355 sal_uInt32 XclExpPaletteImpl::GetColorIdFromIndex( sal_uInt16 nIndex )
356 {
357 return EXC_PAL_INDEXBASE | nIndex;
358 }
359
Finalize()360 void XclExpPaletteImpl::Finalize()
361 {
362 // --- build initial color ID data vector (maColorIdDataVec) ---
363
364 sal_uInt32 nCount = mxColorList->Count();
365 maColorIdDataVec.resize( nCount );
366 for( sal_uInt32 nIdx = 0; nIdx < nCount; ++nIdx )
367 {
368 XclListColor* pListColor = mxColorList->GetObject( nIdx );
369 maColorIdDataVec[ pListColor->GetColorId() ].Set( pListColor->GetColor(), nIdx );
370 }
371
372 // --- loop as long as current color count does not fit into palette of current BIFF ---
373
374 // phase 1: raw reduction (performance reasons, #i36945#)
375 sal_uInt32 nPass = 0;
376 while( mxColorList->Count() > EXC_PAL_MAXRAWSIZE )
377 RawReducePalette( nPass++ );
378
379 // phase 2: precise reduction using advanced color merging based on color weighting
380 while( mxColorList->Count() > mrDefPal.GetColorCount() )
381 ReduceLeastUsedColor();
382
383 // --- #104865# use default palette and replace colors with nearest used colors ---
384
385 nCount = mxColorList->Count();
386 XclRemapVec aRemapVec( nCount );
387 XclNearestVec aNearestVec( nCount );
388
389 // in each run: search the best fitting color and replace a default color with it
390 for( sal_uInt32 nRun = 0; nRun < nCount; ++nRun )
391 {
392 sal_uInt32 nIndex;
393 // find nearest unused default color for each unprocessed list color
394 for( nIndex = 0; nIndex < nCount; ++nIndex )
395 aNearestVec[ nIndex ].mnDist = aRemapVec[ nIndex ].mbProcessed ? SAL_MAX_INT32 :
396 GetNearestPaletteColor( aNearestVec[ nIndex ].mnPalIndex, mxColorList->GetObject( nIndex )->GetColor(), true );
397 // find the list color which is nearest to a default color
398 sal_uInt32 nFound = 0;
399 for( nIndex = 1; nIndex < nCount; ++nIndex )
400 if( aNearestVec[ nIndex ].mnDist < aNearestVec[ nFound ].mnDist )
401 nFound = nIndex;
402 // replace default color with list color
403 sal_uInt32 nNearest = aNearestVec[ nFound ].mnPalIndex;
404 DBG_ASSERT( mxColorList->GetObject( nFound ), "XclExpPaletteImpl::Finalize - missing a color" );
405 DBG_ASSERT( nNearest < maPalette.size(), "XclExpPaletteImpl::Finalize - algorithm error" );
406 maPalette[ nNearest ].SetColor( mxColorList->GetObject( nFound )->GetColor() );
407 aRemapVec[ nFound ].SetIndex( nNearest );
408 }
409
410 // remap color ID data map (maColorIdDataVec) from list indexes to palette indexes
411 for( XclColorIdDataVec::iterator aIt = maColorIdDataVec.begin(), aEnd = maColorIdDataVec.end(); aIt != aEnd; ++aIt )
412 aIt->mnIndex = aRemapVec[ aIt->mnIndex ].mnPalIndex;
413 }
414
GetColorIndex(sal_uInt32 nColorId) const415 sal_uInt16 XclExpPaletteImpl::GetColorIndex( sal_uInt32 nColorId ) const
416 {
417 sal_uInt16 nRet = 0;
418 if( nColorId >= EXC_PAL_INDEXBASE )
419 nRet = static_cast< sal_uInt16 >( nColorId & ~EXC_PAL_INDEXBASE );
420 else if( nColorId < maColorIdDataVec.size() )
421 nRet = GetXclIndex( maColorIdDataVec[ nColorId ].mnIndex );
422 return nRet;
423 }
424
GetMixedColors(sal_uInt16 & rnXclForeIx,sal_uInt16 & rnXclBackIx,sal_uInt8 & rnXclPattern,sal_uInt32 nForeColorId,sal_uInt32 nBackColorId) const425 void XclExpPaletteImpl::GetMixedColors(
426 sal_uInt16& rnXclForeIx, sal_uInt16& rnXclBackIx, sal_uInt8& rnXclPattern,
427 sal_uInt32 nForeColorId, sal_uInt32 nBackColorId ) const
428 {
429 rnXclForeIx = GetColorIndex( nForeColorId );
430 rnXclBackIx = GetColorIndex( nBackColorId );
431 if( (rnXclPattern != EXC_PATT_SOLID) || (nForeColorId >= maColorIdDataVec.size()) )
432 return;
433
434 // now we have solid pattern, and a defined foreground (background doesn't care for solid pattern)
435
436 sal_uInt32 nIndex1, nIndex2;
437 Color aForeColor( GetOriginalColor( nForeColorId ) );
438 sal_Int32 nFirstDist = GetNearPaletteColors( nIndex1, nIndex2, aForeColor );
439 if( (nIndex1 >= maPalette.size()) || (nIndex2 >= maPalette.size()) )
440 return;
441
442 Color aColorArr[ 5 ];
443 aColorArr[ 0 ] = maPalette[ nIndex1 ].maColor;
444 aColorArr[ 4 ] = maPalette[ nIndex2 ].maColor;
445 lclSetMixedColor( aColorArr[ 2 ], aColorArr[ 0 ], aColorArr[ 4 ] );
446 lclSetMixedColor( aColorArr[ 1 ], aColorArr[ 0 ], aColorArr[ 2 ] );
447 lclSetMixedColor( aColorArr[ 3 ], aColorArr[ 2 ], aColorArr[ 4 ] );
448
449 sal_Int32 nMinDist = nFirstDist;
450 sal_uInt32 nMinIndex = 0;
451 for( sal_uInt32 nCnt = 1; nCnt < 4; ++nCnt )
452 {
453 sal_Int32 nDist = lclGetColorDistance( aForeColor, aColorArr[ nCnt ] );
454 if( nDist < nMinDist )
455 {
456 nMinDist = nDist;
457 nMinIndex = nCnt;
458 }
459 }
460 rnXclForeIx = GetXclIndex( nIndex1 );
461 rnXclBackIx = GetXclIndex( nIndex2 );
462 if( nMinDist < nFirstDist )
463 {
464 switch( nMinIndex )
465 {
466 case 1: rnXclPattern = EXC_PATT_75_PERC; break;
467 case 2: rnXclPattern = EXC_PATT_50_PERC; break;
468 case 3: rnXclPattern = EXC_PATT_25_PERC; break;
469 }
470 }
471 }
472
GetColorData(sal_uInt16 nXclIndex) const473 ColorData XclExpPaletteImpl::GetColorData( sal_uInt16 nXclIndex ) const
474 {
475 if( nXclIndex >= EXC_COLOR_USEROFFSET )
476 {
477 sal_uInt32 nIdx = nXclIndex - EXC_COLOR_USEROFFSET;
478 if( nIdx < maPalette.size() )
479 return maPalette[ nIdx ].maColor.GetColor();
480 }
481 return mrDefPal.GetDefColorData( nXclIndex );
482 }
483
IsDefaultPalette() const484 bool XclExpPaletteImpl::IsDefaultPalette() const
485 {
486 bool bDefault = true;
487 for( sal_uInt32 nIdx = 0, nSize = static_cast< sal_uInt32 >( maPalette.size() ); bDefault && (nIdx < nSize); ++nIdx )
488 bDefault = maPalette[ nIdx ].maColor == mrDefPal.GetDefColor( GetXclIndex( nIdx ) );
489 return bDefault;
490 }
491
WriteBody(XclExpStream & rStrm)492 void XclExpPaletteImpl::WriteBody( XclExpStream& rStrm )
493 {
494 rStrm << static_cast< sal_uInt16 >( maPalette.size() );
495 for( XclPaletteColorVec::const_iterator aIt = maPalette.begin(), aEnd = maPalette.end(); aIt != aEnd; ++aIt )
496 rStrm << aIt->maColor;
497 }
498
SaveXml(XclExpXmlStream & rStrm)499 void XclExpPaletteImpl::SaveXml( XclExpXmlStream& rStrm )
500 {
501 if( !maPalette.size() )
502 return;
503
504 sax_fastparser::FSHelperPtr& rStyleSheet = rStrm.GetCurrentStream();
505 rStyleSheet->startElement( XML_colors, FSEND );
506 rStyleSheet->startElement( XML_indexedColors, FSEND );
507 for( XclPaletteColorVec::const_iterator aIt = maPalette.begin(), aEnd = maPalette.end(); aIt != aEnd; ++aIt )
508 rStyleSheet->singleElement( XML_rgbColor,
509 XML_rgb, XclXmlUtils::ToOString( aIt->maColor ).getStr(),
510 FSEND );
511 rStyleSheet->endElement( XML_indexedColors );
512 rStyleSheet->endElement( XML_colors );
513 }
514
GetOriginalColor(sal_uInt32 nColorId) const515 const Color& XclExpPaletteImpl::GetOriginalColor( sal_uInt32 nColorId ) const
516 {
517 if( nColorId < maColorIdDataVec.size() )
518 return maColorIdDataVec[ nColorId ].maColor;
519 return maPalette[ 0 ].maColor;
520 }
521
SearchListEntry(const Color & rColor,sal_uInt32 & rnIndex)522 XclListColor* XclExpPaletteImpl::SearchListEntry( const Color& rColor, sal_uInt32& rnIndex )
523 {
524 rnIndex = mnLastIdx;
525 XclListColor* pEntry = mxColorList->GetObject( rnIndex );
526
527 // search optimization for equal-colored objects occurring repeatedly
528 if( pEntry && (pEntry->GetColor() == rColor) )
529 return pEntry;
530
531 // binary search for color
532 sal_uInt32 nBegIdx = 0;
533 sal_uInt32 nEndIdx = mxColorList->Count();
534 bool bFound = false;
535 while( !bFound && (nBegIdx < nEndIdx) )
536 {
537 rnIndex = (nBegIdx + nEndIdx) / 2;
538 pEntry = mxColorList->GetObject( rnIndex );
539 bFound = pEntry->GetColor() == rColor;
540 if( !bFound )
541 {
542 if( pEntry->GetColor().GetColor() < rColor.GetColor() )
543 nBegIdx = rnIndex + 1;
544 else
545 nEndIdx = rnIndex;
546 }
547 }
548 // not found - use end of range as new insertion position
549 if( !bFound )
550 pEntry = mxColorList->GetObject( rnIndex = nEndIdx );
551
552 mnLastIdx = rnIndex;
553 return pEntry;
554 }
555
CreateListEntry(const Color & rColor,sal_uInt32 nIndex)556 XclListColor* XclExpPaletteImpl::CreateListEntry( const Color& rColor, sal_uInt32 nIndex )
557 {
558 XclListColor* pEntry = new XclListColor( rColor, mxColorList->Count() );
559 mxColorList->Insert( pEntry, nIndex );
560 return pEntry;
561 }
562
RawReducePalette(sal_uInt32 nPass)563 void XclExpPaletteImpl::RawReducePalette( sal_uInt32 nPass )
564 {
565 /* Fast palette reduction - in each call of this function one RGB component
566 of each color is reduced to a lower number of distinct values.
567 Pass 0: Blue is reduced to 128 distinct values.
568 Pass 1: Red is reduced to 128 distinct values.
569 Pass 2: Green is reduced to 128 distinct values.
570 Pass 3: Blue is reduced to 64 distinct values.
571 Pass 4: Red is reduced to 64 distinct values.
572 Pass 5: Green is reduced to 64 distinct values.
573 And so on...
574 */
575
576 XclListColorListRef xOldList = mxColorList;
577 mxColorList.reset( new XclListColorList );
578
579 // maps old list indexes to new list indexes, used to update maColorIdDataVec
580 ScfUInt32Vec aListIndexMap;
581 aListIndexMap.reserve( xOldList->Count() );
582
583 // preparations
584 sal_uInt8 nR, nG, nB;
585 sal_uInt8& rnComp = ((nPass % 3 == 0) ? nB : ((nPass % 3 == 1) ? nR : nG));
586 nPass /= 3;
587 DBG_ASSERT( nPass < 7, "XclExpPaletteImpl::RawReducePalette - reduction not terminated" );
588
589 static const sal_uInt8 spnFactor2[] = { 0x81, 0x82, 0x84, 0x88, 0x92, 0xAA, 0xFF };
590 sal_uInt8 nFactor1 = static_cast< sal_uInt8 >( 0x02 << nPass );
591 sal_uInt8 nFactor2 = spnFactor2[ nPass ];
592 sal_uInt8 nFactor3 = static_cast< sal_uInt8 >( 0x40 >> nPass );
593
594 // process each color in the old color list
595 for( sal_uInt32 nIdx = 0, nCount = xOldList->Count(); nIdx < nCount; ++nIdx )
596 {
597 // get the old list entry
598 const XclListColor* pOldEntry = xOldList->GetObject( nIdx );
599 nR = pOldEntry->GetColor().GetRed();
600 nG = pOldEntry->GetColor().GetGreen();
601 nB = pOldEntry->GetColor().GetBlue();
602
603 /* Calculate the new RGB component (rnComp points to one of nR, nG, nB).
604 Using integer arithmetic with its rounding errors, the results of
605 this calculation are always exactly in the range 0x00 to 0xFF
606 (simply cutting the lower bits would darken the colors slightly). */
607 sal_uInt32 nNewComp = rnComp;
608 nNewComp /= nFactor1;
609 nNewComp *= nFactor2;
610 nNewComp /= nFactor3;
611 rnComp = static_cast< sal_uInt8 >( nNewComp );
612 Color aNewColor( nR, nG, nB );
613
614 // find or insert the new color
615 sal_uInt32 nFoundIdx = 0;
616 XclListColor* pNewEntry = SearchListEntry( aNewColor, nFoundIdx );
617 if( !pNewEntry || (pNewEntry->GetColor() != aNewColor) )
618 pNewEntry = CreateListEntry( aNewColor, nFoundIdx );
619 pNewEntry->AddWeighting( pOldEntry->GetWeighting() );
620 aListIndexMap.push_back( nFoundIdx );
621 }
622
623 // update color ID data map (maps color IDs to color list indexes), replace old by new list indexes
624 for( XclColorIdDataVec::iterator aIt = maColorIdDataVec.begin(), aEnd = maColorIdDataVec.end(); aIt != aEnd; ++aIt )
625 aIt->mnIndex = aListIndexMap[ aIt->mnIndex ];
626 }
627
ReduceLeastUsedColor()628 void XclExpPaletteImpl::ReduceLeastUsedColor()
629 {
630 // find a list color to remove
631 sal_uInt32 nRemove = GetLeastUsedListColor();
632 // find its nearest neighbor
633 sal_uInt32 nKeep = GetNearestListColor( nRemove );
634
635 // merge both colors to one color, remove one color from list
636 XclListColor* pKeepEntry = mxColorList->GetObject( nKeep );
637 XclListColor* pRemoveEntry = mxColorList->GetObject( nRemove );
638 if( pKeepEntry && pRemoveEntry )
639 {
640 // merge both colors (if pKeepEntry is a base color, it will not change)
641 pKeepEntry->Merge( *pRemoveEntry );
642 // remove the less used color, adjust nKeep index if kept color follows removed color
643 mxColorList->Delete( nRemove );
644 if( nKeep > nRemove ) --nKeep;
645
646 // recalculate color ID data map (maps color IDs to color list indexes)
647 for( XclColorIdDataVec::iterator aIt = maColorIdDataVec.begin(), aEnd = maColorIdDataVec.end(); aIt != aEnd; ++aIt )
648 {
649 if( aIt->mnIndex > nRemove )
650 --aIt->mnIndex;
651 else if( aIt->mnIndex == nRemove )
652 aIt->mnIndex = nKeep;
653 }
654 }
655 }
656
GetLeastUsedListColor() const657 sal_uInt32 XclExpPaletteImpl::GetLeastUsedListColor() const
658 {
659 sal_uInt32 nFound = 0;
660 sal_uInt32 nMinW = SAL_MAX_UINT32;
661
662 for( sal_uInt32 nIdx = 0, nCount = mxColorList->Count(); nIdx < nCount; ++nIdx )
663 {
664 XclListColor* pEntry = mxColorList->GetObject( nIdx );
665 // ignore the base colors
666 if( !pEntry->IsBaseColor() && (pEntry->GetWeighting() < nMinW) )
667 {
668 nFound = nIdx;
669 nMinW = pEntry->GetWeighting();
670 }
671 }
672 return nFound;
673 }
674
GetNearestListColor(const Color & rColor,sal_uInt32 nIgnore) const675 sal_uInt32 XclExpPaletteImpl::GetNearestListColor( const Color& rColor, sal_uInt32 nIgnore ) const
676 {
677 sal_uInt32 nFound = 0;
678 sal_Int32 nMinD = SAL_MAX_INT32;
679
680 for( sal_uInt32 nIdx = 0, nCount = mxColorList->Count(); nIdx < nCount; ++nIdx )
681 {
682 if( nIdx != nIgnore )
683 {
684 if( XclListColor* pEntry = mxColorList->GetObject( nIdx ) )
685 {
686 sal_Int32 nDist = lclGetColorDistance( rColor, pEntry->GetColor() );
687 if( nDist < nMinD )
688 {
689 nFound = nIdx;
690 nMinD = nDist;
691 }
692 }
693 }
694 }
695 return nFound;
696 }
697
GetNearestListColor(sal_uInt32 nIndex) const698 sal_uInt32 XclExpPaletteImpl::GetNearestListColor( sal_uInt32 nIndex ) const
699 {
700 XclListColor* pEntry = mxColorList->GetObject( nIndex );
701 return pEntry ? GetNearestListColor( pEntry->GetColor(), nIndex ) : 0;
702 }
703
GetNearestPaletteColor(sal_uInt32 & rnIndex,const Color & rColor,bool bDefaultOnly) const704 sal_Int32 XclExpPaletteImpl::GetNearestPaletteColor(
705 sal_uInt32& rnIndex, const Color& rColor, bool bDefaultOnly ) const
706 {
707 rnIndex = 0;
708 sal_Int32 nDist = SAL_MAX_INT32;
709
710 for( XclPaletteColorVec::const_iterator aIt = maPalette.begin(), aEnd = maPalette.end();
711 aIt != aEnd; ++aIt )
712 {
713 if( !bDefaultOnly || !aIt->mbUsed )
714 {
715 sal_Int32 nCurrDist = lclGetColorDistance( rColor, aIt->maColor );
716 if( nCurrDist < nDist )
717 {
718 rnIndex = aIt - maPalette.begin();
719 nDist = nCurrDist;
720 }
721 }
722 }
723 return nDist;
724 }
725
GetNearPaletteColors(sal_uInt32 & rnFirst,sal_uInt32 & rnSecond,const Color & rColor) const726 sal_Int32 XclExpPaletteImpl::GetNearPaletteColors(
727 sal_uInt32& rnFirst, sal_uInt32& rnSecond, const Color& rColor ) const
728 {
729 rnFirst = rnSecond = 0;
730 sal_Int32 nDist1 = SAL_MAX_INT32;
731 sal_Int32 nDist2 = SAL_MAX_INT32;
732
733 for( XclPaletteColorVec::const_iterator aIt = maPalette.begin(), aEnd = maPalette.end();
734 aIt != aEnd; ++aIt )
735 {
736 sal_Int32 nCurrDist = lclGetColorDistance( rColor, aIt->maColor );
737 if( nCurrDist < nDist1 )
738 {
739 rnSecond = rnFirst;
740 nDist2 = nDist1;
741 rnFirst = aIt - maPalette.begin();
742 nDist1 = nCurrDist;
743 }
744 else if( nCurrDist < nDist2 )
745 {
746 rnSecond = aIt - maPalette.begin();
747 nDist2 = nCurrDist;
748 }
749 }
750 return nDist1;
751 }
752
753 // ----------------------------------------------------------------------------
754
XclExpPalette(const XclExpRoot & rRoot)755 XclExpPalette::XclExpPalette( const XclExpRoot& rRoot ) :
756 XclDefaultPalette( rRoot ),
757 XclExpRecord( EXC_ID_PALETTE )
758 {
759 mxImpl.reset( new XclExpPaletteImpl( *this ) );
760 SetRecSize( GetColorCount() * 4 + 2 );
761 }
762
~XclExpPalette()763 XclExpPalette::~XclExpPalette()
764 {
765 }
766
InsertColor(const Color & rColor,XclExpColorType eType,sal_uInt16 nAutoDefault)767 sal_uInt32 XclExpPalette::InsertColor( const Color& rColor, XclExpColorType eType, sal_uInt16 nAutoDefault )
768 {
769 return mxImpl->InsertColor( rColor, eType, nAutoDefault );
770 }
771
GetColorIdFromIndex(sal_uInt16 nIndex)772 sal_uInt32 XclExpPalette::GetColorIdFromIndex( sal_uInt16 nIndex )
773 {
774 return XclExpPaletteImpl::GetColorIdFromIndex( nIndex );
775 }
776
Finalize()777 void XclExpPalette::Finalize()
778 {
779 mxImpl->Finalize();
780 }
781
GetColorIndex(sal_uInt32 nColorId) const782 sal_uInt16 XclExpPalette::GetColorIndex( sal_uInt32 nColorId ) const
783 {
784 return mxImpl->GetColorIndex( nColorId );
785 }
786
GetMixedColors(sal_uInt16 & rnXclForeIx,sal_uInt16 & rnXclBackIx,sal_uInt8 & rnXclPattern,sal_uInt32 nForeColorId,sal_uInt32 nBackColorId) const787 void XclExpPalette::GetMixedColors(
788 sal_uInt16& rnXclForeIx, sal_uInt16& rnXclBackIx, sal_uInt8& rnXclPattern,
789 sal_uInt32 nForeColorId, sal_uInt32 nBackColorId ) const
790 {
791 return mxImpl->GetMixedColors( rnXclForeIx, rnXclBackIx, rnXclPattern, nForeColorId, nBackColorId );
792 }
793
GetColorData(sal_uInt16 nXclIndex) const794 ColorData XclExpPalette::GetColorData( sal_uInt16 nXclIndex ) const
795 {
796 return mxImpl->GetColorData( nXclIndex );
797 }
798
Save(XclExpStream & rStrm)799 void XclExpPalette::Save( XclExpStream& rStrm )
800 {
801 if( !mxImpl->IsDefaultPalette() )
802 XclExpRecord::Save( rStrm );
803 }
804
SaveXml(XclExpXmlStream & rStrm)805 void XclExpPalette::SaveXml( XclExpXmlStream& rStrm )
806 {
807 if( !mxImpl->IsDefaultPalette() )
808 mxImpl->SaveXml( rStrm );
809 }
810
WriteBody(XclExpStream & rStrm)811 void XclExpPalette::WriteBody( XclExpStream& rStrm )
812 {
813 mxImpl->WriteBody( rStrm );
814 }
815
816 // FONT record - font information =============================================
817
818 namespace {
819
820 typedef ::std::pair< sal_uInt16, sal_Int16 > WhichAndScript;
821
lclCheckFontItems(const SfxItemSet & rItemSet,const WhichAndScript & rWAS1,const WhichAndScript & rWAS2,const WhichAndScript & rWAS3)822 sal_Int16 lclCheckFontItems( const SfxItemSet& rItemSet,
823 const WhichAndScript& rWAS1, const WhichAndScript& rWAS2, const WhichAndScript& rWAS3 )
824 {
825 if( ScfTools::CheckItem( rItemSet, rWAS1.first, false ) ) return rWAS1.second;
826 if( ScfTools::CheckItem( rItemSet, rWAS2.first, false ) ) return rWAS2.second;
827 if( ScfTools::CheckItem( rItemSet, rWAS3.first, false ) ) return rWAS3.second;
828 return 0;
829 };
830
831 } // namespace
832
GetFirstUsedScript(const XclExpRoot & rRoot,const SfxItemSet & rItemSet)833 /*static*/ sal_Int16 XclExpFontHelper::GetFirstUsedScript( const XclExpRoot& rRoot, const SfxItemSet& rItemSet )
834 {
835 namespace ApiScriptType = ::com::sun::star::i18n::ScriptType;
836
837 /* #i17050# #i107170# We need to determine which font items are set in the
838 item set, and which script type we should prefer according to the
839 current language settings. */
840
841 static const WhichAndScript WAS_LATIN( ATTR_FONT, ::com::sun::star::i18n::ScriptType::LATIN );
842 static const WhichAndScript WAS_ASIAN( ATTR_CJK_FONT, ::com::sun::star::i18n::ScriptType::ASIAN );
843 static const WhichAndScript WAS_CMPLX( ATTR_CTL_FONT, ::com::sun::star::i18n::ScriptType::COMPLEX );
844
845 /* #114008# do not let a font from a parent style override an explicit
846 cell font. */
847
848 sal_Int16 nDefScript = rRoot.GetDefApiScript();
849 sal_Int16 nScript = 0;
850 const SfxItemSet* pCurrSet = &rItemSet;
851
852 while( (nScript == 0) && pCurrSet )
853 {
854 switch( nDefScript )
855 {
856 case ApiScriptType::LATIN:
857 nScript = lclCheckFontItems( *pCurrSet, WAS_LATIN, WAS_CMPLX, WAS_ASIAN );
858 break;
859 case ApiScriptType::ASIAN:
860 nScript = lclCheckFontItems( *pCurrSet, WAS_ASIAN, WAS_CMPLX, WAS_LATIN );
861 break;
862 case ApiScriptType::COMPLEX:
863 nScript = lclCheckFontItems( *pCurrSet, WAS_CMPLX, WAS_ASIAN, WAS_LATIN );
864 break;
865 default:
866 DBG_ERRORFILE( "XclExpFontHelper::GetFirstUsedScript - unknown script type" );
867 nScript = ApiScriptType::LATIN;
868 };
869 pCurrSet = pCurrSet->GetParent();
870 }
871
872 return nScript;
873 }
874
GetFontFromItemSet(const XclExpRoot & rRoot,const SfxItemSet & rItemSet,sal_Int16 nScript)875 /*static*/ Font XclExpFontHelper::GetFontFromItemSet( const XclExpRoot& rRoot, const SfxItemSet& rItemSet, sal_Int16 nScript )
876 {
877 namespace ApiScriptType = ::com::sun::star::i18n::ScriptType;
878
879 // if WEAK is passed, guess script type from existing items in the item set
880 if( nScript == ApiScriptType::WEAK )
881 nScript = GetFirstUsedScript( rRoot, rItemSet );
882
883 // convert to core script type constants
884 sal_uInt8 nScScript = SCRIPTTYPE_LATIN;
885 switch( nScript )
886 {
887 case ApiScriptType::LATIN: nScScript = SCRIPTTYPE_LATIN; break;
888 case ApiScriptType::ASIAN: nScScript = SCRIPTTYPE_ASIAN; break;
889 case ApiScriptType::COMPLEX: nScScript = SCRIPTTYPE_COMPLEX; break;
890 default: DBG_ERRORFILE( "XclExpFontHelper::GetFontFromItemSet - unknown script type" );
891 }
892
893 // fill the font object
894 Font aFont;
895 ScPatternAttr::GetFont( aFont, rItemSet, SC_AUTOCOL_RAW, 0, 0, 0, nScScript );
896 return aFont;
897 }
898
CheckItems(const XclExpRoot & rRoot,const SfxItemSet & rItemSet,sal_Int16 nScript,bool bDeep)899 /*static*/ bool XclExpFontHelper::CheckItems( const XclExpRoot& rRoot, const SfxItemSet& rItemSet, sal_Int16 nScript, bool bDeep )
900 {
901 static const sal_uInt16 pnCommonIds[] = {
902 ATTR_FONT_UNDERLINE, ATTR_FONT_CROSSEDOUT, ATTR_FONT_CONTOUR,
903 ATTR_FONT_SHADOWED, ATTR_FONT_COLOR, ATTR_FONT_LANGUAGE, 0 };
904 static const sal_uInt16 pnLatinIds[] = {
905 ATTR_FONT, ATTR_FONT_HEIGHT, ATTR_FONT_WEIGHT, ATTR_FONT_POSTURE, 0 };
906 static const sal_uInt16 pnAsianIds[] = {
907 ATTR_CJK_FONT, ATTR_CJK_FONT_HEIGHT, ATTR_CJK_FONT_WEIGHT, ATTR_CJK_FONT_POSTURE, 0 };
908 static const sal_uInt16 pnComplexIds[] = {
909 ATTR_CTL_FONT, ATTR_CTL_FONT_HEIGHT, ATTR_CTL_FONT_WEIGHT, ATTR_CTL_FONT_POSTURE, 0 };
910
911 bool bUsed = ScfTools::CheckItems( rItemSet, pnCommonIds, bDeep );
912 if( !bUsed )
913 {
914 namespace ApiScriptType = ::com::sun::star::i18n::ScriptType;
915 // if WEAK is passed, guess script type from existing items in the item set
916 if( nScript == ApiScriptType::WEAK )
917 nScript = GetFirstUsedScript( rRoot, rItemSet );
918 // check the correct items
919 switch( nScript )
920 {
921 case ApiScriptType::LATIN: bUsed = ScfTools::CheckItems( rItemSet, pnLatinIds, bDeep ); break;
922 case ApiScriptType::ASIAN: bUsed = ScfTools::CheckItems( rItemSet, pnAsianIds, bDeep ); break;
923 case ApiScriptType::COMPLEX: bUsed = ScfTools::CheckItems( rItemSet, pnComplexIds, bDeep ); break;
924 default: DBG_ERRORFILE( "XclExpFontHelper::CheckItems - unknown script type" );
925 }
926 }
927 return bUsed;
928 }
929
930 // ----------------------------------------------------------------------------
931
932 namespace {
933
lclCalcHash(const XclFontData & rFontData)934 sal_uInt32 lclCalcHash( const XclFontData& rFontData )
935 {
936 sal_uInt32 nHash = rFontData.maName.Len();
937 nHash += rFontData.maColor.GetColor() * 2;
938 nHash += rFontData.mnWeight * 3;
939 nHash += rFontData.mnCharSet * 5;
940 nHash += rFontData.mnFamily * 7;
941 nHash += rFontData.mnHeight * 11;
942 nHash += rFontData.mnUnderline * 13;
943 nHash += rFontData.mnEscapem * 17;
944 if( rFontData.mbItalic ) nHash += 19;
945 if( rFontData.mbStrikeout ) nHash += 23;
946 if( rFontData.mbOutline ) nHash += 29;
947 if( rFontData.mbShadow ) nHash += 31;
948 return nHash;
949 }
950
951 } // namespace
952
953 // ----------------------------------------------------------------------------
954
XclExpFont(const XclExpRoot & rRoot,const XclFontData & rFontData,XclExpColorType eColorType)955 XclExpFont::XclExpFont( const XclExpRoot& rRoot,
956 const XclFontData& rFontData, XclExpColorType eColorType ) :
957 XclExpRecord( EXC_ID2_FONT, 14 ),
958 XclExpRoot( rRoot ),
959 maData( rFontData )
960 {
961 // insert font color into palette
962 mnColorId = rRoot.GetPalette().InsertColor( rFontData.maColor, eColorType, EXC_COLOR_FONTAUTO );
963 // hash value for faster comparison
964 mnHash = lclCalcHash( maData );
965 // record size
966 sal_Size nStrLen = maData.maName.Len();
967 SetRecSize( ((GetBiff() == EXC_BIFF8) ? (nStrLen * 2 + 1) : nStrLen) + 15 );
968 }
969
Equals(const XclFontData & rFontData,sal_uInt32 nHash) const970 bool XclExpFont::Equals( const XclFontData& rFontData, sal_uInt32 nHash ) const
971 {
972 return (mnHash == nHash) && (maData == rFontData);
973 }
974
SaveXml(XclExpXmlStream & rStrm)975 void XclExpFont::SaveXml( XclExpXmlStream& rStrm )
976 {
977 sax_fastparser::FSHelperPtr& rStyleSheet = rStrm.GetCurrentStream();
978 rStyleSheet->startElement( XML_font, FSEND );
979 rStrm.WriteFontData( maData, XML_name );
980 // OOXTODO: XML_scheme; //scheme/@val values: "major", "minor", "none"
981 rStyleSheet->endElement( XML_font );
982 }
983
984 // private --------------------------------------------------------------------
985
WriteBody(XclExpStream & rStrm)986 void XclExpFont::WriteBody( XclExpStream& rStrm )
987 {
988 sal_uInt16 nAttr = EXC_FONTATTR_NONE;
989 ::set_flag( nAttr, EXC_FONTATTR_ITALIC, maData.mbItalic );
990 ::set_flag( nAttr, EXC_FONTATTR_STRIKEOUT, maData.mbStrikeout );
991 ::set_flag( nAttr, EXC_FONTATTR_OUTLINE, maData.mbOutline );
992 ::set_flag( nAttr, EXC_FONTATTR_SHADOW, maData.mbShadow );
993
994 DBG_ASSERT( maData.maName.Len() < 256, "XclExpFont::WriteBody - font name too long" );
995 XclExpString aFontName;
996 if( GetBiff() <= EXC_BIFF5 )
997 aFontName.AssignByte( maData.maName, GetTextEncoding(), EXC_STR_8BITLENGTH );
998 else
999 aFontName.Assign( maData.maName, EXC_STR_FORCEUNICODE | EXC_STR_8BITLENGTH );
1000
1001 rStrm << maData.mnHeight
1002 << nAttr
1003 << GetPalette().GetColorIndex( mnColorId )
1004 << maData.mnWeight
1005 << maData.mnEscapem
1006 << maData.mnUnderline
1007 << maData.mnFamily
1008 << maData.mnCharSet
1009 << sal_uInt8( 0 )
1010 << aFontName;
1011 }
1012
1013 // ----------------------------------------------------------------------------
1014
XclExpBlindFont(const XclExpRoot & rRoot)1015 XclExpBlindFont::XclExpBlindFont( const XclExpRoot& rRoot ) :
1016 XclExpFont( rRoot, XclFontData(), EXC_COLOR_CELLTEXT )
1017 {
1018 }
1019
Equals(const XclFontData &,sal_uInt32) const1020 bool XclExpBlindFont::Equals( const XclFontData& /*rFontData*/, sal_uInt32 /*nHash*/ ) const
1021 {
1022 return false;
1023 }
1024
Save(XclExpStream &)1025 void XclExpBlindFont::Save( XclExpStream& /*rStrm*/ )
1026 {
1027 // do nothing
1028 }
1029
1030 // ============================================================================
1031
XclExpFontBuffer(const XclExpRoot & rRoot)1032 XclExpFontBuffer::XclExpFontBuffer( const XclExpRoot& rRoot ) :
1033 XclExpRoot( rRoot ),
1034 mnXclMaxSize( 0 )
1035 {
1036 switch( GetBiff() )
1037 {
1038 case EXC_BIFF4: mnXclMaxSize = EXC_FONT_MAXCOUNT4; break;
1039 case EXC_BIFF5: mnXclMaxSize = EXC_FONT_MAXCOUNT5; break;
1040 case EXC_BIFF8: mnXclMaxSize = EXC_FONT_MAXCOUNT8; break;
1041 default: DBG_ERROR_BIFF();
1042 }
1043 InitDefaultFonts();
1044 }
1045
GetFont(sal_uInt16 nXclFont) const1046 const XclExpFont* XclExpFontBuffer::GetFont( sal_uInt16 nXclFont ) const
1047 {
1048 return maFontList.GetRecord( nXclFont ).get();
1049 }
1050
GetAppFontData() const1051 const XclFontData& XclExpFontBuffer::GetAppFontData() const
1052 {
1053 return maFontList.GetRecord( EXC_FONT_APP )->GetFontData(); // exists always
1054 }
1055
Insert(const XclFontData & rFontData,XclExpColorType eColorType,bool bAppFont)1056 sal_uInt16 XclExpFontBuffer::Insert(
1057 const XclFontData& rFontData, XclExpColorType eColorType, bool bAppFont )
1058 {
1059 if( bAppFont )
1060 {
1061 XclExpFontRef xFont( new XclExpFont( GetRoot(), rFontData, eColorType ) );
1062 maFontList.ReplaceRecord( xFont, EXC_FONT_APP );
1063 // #108487# set width of '0' character for column width export
1064 SetCharWidth( xFont->GetFontData() );
1065 return EXC_FONT_APP;
1066 }
1067
1068 size_t nPos = Find( rFontData );
1069 if( nPos == EXC_FONTLIST_NOTFOUND )
1070 {
1071 // not found in buffer - create new font
1072 size_t nSize = maFontList.GetSize();
1073 if( nSize < mnXclMaxSize )
1074 {
1075 // possible to insert
1076 maFontList.AppendNewRecord( new XclExpFont( GetRoot(), rFontData, eColorType ) );
1077 nPos = nSize; // old size is last position now
1078 }
1079 else
1080 {
1081 // buffer is full - ignore new font, use default font
1082 nPos = EXC_FONT_APP;
1083 }
1084 }
1085 return static_cast< sal_uInt16 >( nPos );
1086 }
1087
Insert(const Font & rFont,XclExpColorType eColorType,bool bAppFont)1088 sal_uInt16 XclExpFontBuffer::Insert(
1089 const Font& rFont, XclExpColorType eColorType, bool bAppFont )
1090 {
1091 return Insert( XclFontData( rFont ), eColorType, bAppFont );
1092 }
1093
Insert(const SvxFont & rFont,XclExpColorType eColorType,bool bAppFont)1094 sal_uInt16 XclExpFontBuffer::Insert(
1095 const SvxFont& rFont, XclExpColorType eColorType, bool bAppFont )
1096 {
1097 return Insert( XclFontData( rFont ), eColorType, bAppFont );
1098 }
1099
Insert(const SfxItemSet & rItemSet,sal_Int16 nScript,XclExpColorType eColorType,bool bAppFont)1100 sal_uInt16 XclExpFontBuffer::Insert( const SfxItemSet& rItemSet,
1101 sal_Int16 nScript, XclExpColorType eColorType, bool bAppFont )
1102 {
1103 // #i17050# #114008# #115495# script type now provided by caller
1104 Font aFont = XclExpFontHelper::GetFontFromItemSet( GetRoot(), rItemSet, nScript );
1105 return Insert( aFont, eColorType, bAppFont );
1106 }
1107
Insert(const ScPatternAttr & rPattern,sal_Int16 nScript,XclExpColorType eColorType,bool bAppFont)1108 sal_uInt16 XclExpFontBuffer::Insert( const ScPatternAttr& rPattern,
1109 sal_Int16 nScript, XclExpColorType eColorType, bool bAppFont )
1110 {
1111 return Insert( rPattern.GetItemSet(), nScript, eColorType, bAppFont );
1112 }
1113
Save(XclExpStream & rStrm)1114 void XclExpFontBuffer::Save( XclExpStream& rStrm )
1115 {
1116 maFontList.Save( rStrm );
1117 }
1118
SaveXml(XclExpXmlStream & rStrm)1119 void XclExpFontBuffer::SaveXml( XclExpXmlStream& rStrm )
1120 {
1121 if( maFontList.IsEmpty() )
1122 return;
1123
1124 sax_fastparser::FSHelperPtr& rStyleSheet = rStrm.GetCurrentStream();
1125 rStyleSheet->startElement( XML_fonts,
1126 XML_count, OString::valueOf( (sal_Int32) maFontList.GetSize() ).getStr(),
1127 FSEND );
1128
1129 maFontList.SaveXml( rStrm );
1130
1131 rStyleSheet->endElement( XML_fonts );
1132 }
1133
1134 // private --------------------------------------------------------------------
1135
InitDefaultFonts()1136 void XclExpFontBuffer::InitDefaultFonts()
1137 {
1138 XclFontData aFontData;
1139 aFontData.maName.AssignAscii( "Arial" );
1140 aFontData.SetScFamily( FAMILY_DONTKNOW );
1141 aFontData.SetFontEncoding( ScfTools::GetSystemTextEncoding() );
1142 aFontData.SetScHeight( 200 ); // 200 twips = 10 pt
1143 aFontData.SetScWeight( WEIGHT_NORMAL );
1144
1145 switch( GetBiff() )
1146 {
1147 case EXC_BIFF5:
1148 {
1149 maFontList.AppendNewRecord( new XclExpFont( GetRoot(), aFontData, EXC_COLOR_CELLTEXT ) );
1150 aFontData.SetScWeight( WEIGHT_BOLD );
1151 maFontList.AppendNewRecord( new XclExpFont( GetRoot(), aFontData, EXC_COLOR_CELLTEXT ) );
1152 aFontData.SetScWeight( WEIGHT_NORMAL );
1153 aFontData.SetScPosture( ITALIC_NORMAL );
1154 maFontList.AppendNewRecord( new XclExpFont( GetRoot(), aFontData, EXC_COLOR_CELLTEXT ) );
1155 aFontData.SetScWeight( WEIGHT_BOLD );
1156 maFontList.AppendNewRecord( new XclExpFont( GetRoot(), aFontData, EXC_COLOR_CELLTEXT ) );
1157 // the blind font with index 4
1158 maFontList.AppendNewRecord( new XclExpBlindFont( GetRoot() ) );
1159 // already add the first user defined font (Excel does it too)
1160 aFontData.SetScWeight( WEIGHT_NORMAL );
1161 aFontData.SetScPosture( ITALIC_NONE );
1162 maFontList.AppendNewRecord( new XclExpFont( GetRoot(), aFontData, EXC_COLOR_CELLTEXT ) );
1163 }
1164 break;
1165 case EXC_BIFF8:
1166 {
1167 XclExpFontRef xFont( new XclExpFont( GetRoot(), aFontData, EXC_COLOR_CELLTEXT ) );
1168 maFontList.AppendRecord( xFont );
1169 maFontList.AppendRecord( xFont );
1170 maFontList.AppendRecord( xFont );
1171 maFontList.AppendRecord( xFont );
1172 if( GetOutput() == EXC_OUTPUT_BINARY )
1173 // the blind font with index 4
1174 maFontList.AppendNewRecord( new XclExpBlindFont( GetRoot() ) );
1175 }
1176 break;
1177 default:
1178 DBG_ERROR_BIFF();
1179 }
1180 }
1181
Find(const XclFontData & rFontData)1182 size_t XclExpFontBuffer::Find( const XclFontData& rFontData )
1183 {
1184 sal_uInt32 nHash = lclCalcHash( rFontData );
1185 for( size_t nPos = 0, nSize = maFontList.GetSize(); nPos < nSize; ++nPos )
1186 if( maFontList.GetRecord( nPos )->Equals( rFontData, nHash ) )
1187 return nPos;
1188 return EXC_FONTLIST_NOTFOUND;
1189 }
1190
1191 // FORMAT record - number formats =============================================
1192
1193 /** Predicate for search algorithm. */
1194 struct XclExpNumFmtPred
1195 {
1196 sal_uLong mnScNumFmt;
XclExpNumFmtPredXclExpNumFmtPred1197 inline explicit XclExpNumFmtPred( sal_uLong nScNumFmt ) : mnScNumFmt( nScNumFmt ) {}
operator ()XclExpNumFmtPred1198 inline bool operator()( const XclExpNumFmt& rFormat ) const
1199 { return rFormat.mnScNumFmt == mnScNumFmt; }
1200 };
1201
1202 // ----------------------------------------------------------------------------
1203
XclExpNumFmtBuffer(const XclExpRoot & rRoot)1204 XclExpNumFmtBuffer::XclExpNumFmtBuffer( const XclExpRoot& rRoot ) :
1205 XclExpRoot( rRoot ),
1206 /* Compiler needs a hint, this doesn't work: new NfKeywordTable;
1207 cannot convert from 'class String *' to 'class String (*)[54]'
1208 The effective result here is class String (*)[54*1] */
1209 mxFormatter( new SvNumberFormatter( rRoot.GetDoc().GetServiceManager(), LANGUAGE_ENGLISH_US ) ),
1210 mpKeywordTable( new NfKeywordTable[ 1 ] ),
1211 mnStdFmt( GetFormatter().GetStandardFormat( ScGlobal::eLnge ) )
1212 {
1213 switch( GetBiff() )
1214 {
1215 case EXC_BIFF5: mnXclOffset = EXC_FORMAT_OFFSET5; break;
1216 case EXC_BIFF8: mnXclOffset = EXC_FORMAT_OFFSET8; break;
1217 default: DBG_ERROR_BIFF();
1218 }
1219
1220 mxFormatter->FillKeywordTable( *mpKeywordTable, LANGUAGE_ENGLISH_US );
1221 // remap codes unknown to Excel
1222 (*mpKeywordTable)[ NF_KEY_NN ] = String( RTL_CONSTASCII_USTRINGPARAM( "DDD" ) );
1223 (*mpKeywordTable)[ NF_KEY_NNN ] = String( RTL_CONSTASCII_USTRINGPARAM( "DDDD" ) );
1224 // NNNN gets a separator appended in SvNumberformat::GetMappedFormatString()
1225 (*mpKeywordTable)[ NF_KEY_NNNN ] = String( RTL_CONSTASCII_USTRINGPARAM( "DDDD" ) );
1226 // Export the Thai T NatNum modifier.
1227 (*mpKeywordTable)[ NF_KEY_THAI_T ] = String( RTL_CONSTASCII_USTRINGPARAM( "T" ) );
1228 }
1229
~XclExpNumFmtBuffer()1230 XclExpNumFmtBuffer::~XclExpNumFmtBuffer()
1231 {
1232 delete[] mpKeywordTable;
1233 }
1234
Insert(sal_uLong nScNumFmt)1235 sal_uInt16 XclExpNumFmtBuffer::Insert( sal_uLong nScNumFmt )
1236 {
1237 XclExpNumFmtVec::const_iterator aIt =
1238 ::std::find_if( maFormatMap.begin(), maFormatMap.end(), XclExpNumFmtPred( nScNumFmt ) );
1239 if( aIt != maFormatMap.end() )
1240 return aIt->mnXclNumFmt;
1241
1242 size_t nSize = maFormatMap.size();
1243 if( nSize < static_cast< size_t >( 0xFFFF - mnXclOffset ) )
1244 {
1245 sal_uInt16 nXclNumFmt = static_cast< sal_uInt16 >( nSize + mnXclOffset );
1246 maFormatMap.push_back( XclExpNumFmt( nScNumFmt, nXclNumFmt ) );
1247 return nXclNumFmt;
1248 }
1249
1250 return 0;
1251 }
1252
Save(XclExpStream & rStrm)1253 void XclExpNumFmtBuffer::Save( XclExpStream& rStrm )
1254 {
1255 for( XclExpNumFmtVec::const_iterator aIt = maFormatMap.begin(), aEnd = maFormatMap.end(); aIt != aEnd; ++aIt )
1256 WriteFormatRecord( rStrm, *aIt );
1257 }
1258
SaveXml(XclExpXmlStream & rStrm)1259 void XclExpNumFmtBuffer::SaveXml( XclExpXmlStream& rStrm )
1260 {
1261 if( !maFormatMap.size() )
1262 return;
1263
1264 sax_fastparser::FSHelperPtr& rStyleSheet = rStrm.GetCurrentStream();
1265 rStyleSheet->startElement( XML_numFmts,
1266 XML_count, OString::valueOf( (sal_Int32) maFormatMap.size() ).getStr(),
1267 FSEND );
1268 for( XclExpNumFmtVec::const_iterator aIt = maFormatMap.begin(), aEnd = maFormatMap.end(); aIt != aEnd; ++aIt )
1269 {
1270 rStyleSheet->singleElement( XML_numFmt,
1271 XML_numFmtId, OString::valueOf( sal_Int32(aIt->mnXclNumFmt) ).getStr(),
1272 XML_formatCode, XclXmlUtils::ToOString( GetFormatCode( *aIt ) ).getStr(),
1273 FSEND );
1274 }
1275 rStyleSheet->endElement( XML_numFmts );
1276 }
1277
WriteFormatRecord(XclExpStream & rStrm,sal_uInt16 nXclNumFmt,const String & rFormatStr)1278 void XclExpNumFmtBuffer::WriteFormatRecord( XclExpStream& rStrm, sal_uInt16 nXclNumFmt, const String& rFormatStr )
1279 {
1280 XclExpString aExpStr;
1281 if( GetBiff() <= EXC_BIFF5 )
1282 aExpStr.AssignByte( rFormatStr, GetTextEncoding(), EXC_STR_8BITLENGTH );
1283 else
1284 aExpStr.Assign( rFormatStr );
1285
1286 rStrm.StartRecord( EXC_ID4_FORMAT, 2 + aExpStr.GetSize() );
1287 rStrm << nXclNumFmt << aExpStr;
1288 rStrm.EndRecord();
1289 }
1290
WriteFormatRecord(XclExpStream & rStrm,const XclExpNumFmt & rFormat)1291 void XclExpNumFmtBuffer::WriteFormatRecord( XclExpStream& rStrm, const XclExpNumFmt& rFormat )
1292 {
1293 WriteFormatRecord( rStrm, rFormat.mnXclNumFmt, GetFormatCode( rFormat ) );
1294 }
1295
GetFormatCode(const XclExpNumFmt & rFormat)1296 String XclExpNumFmtBuffer::GetFormatCode( const XclExpNumFmt& rFormat )
1297 {
1298 String aFormatStr;
1299
1300 if( const SvNumberformat* pEntry = GetFormatter().GetEntry( rFormat.mnScNumFmt ) )
1301 {
1302 if( pEntry->GetType() == NUMBERFORMAT_LOGICAL )
1303 {
1304 // build Boolean number format
1305 Color* pColor = 0;
1306 String aTemp;
1307 const_cast< SvNumberformat* >( pEntry )->GetOutputString( 1.0, aTemp, &pColor );
1308 aFormatStr.Append( '"' ).Append( aTemp ).AppendAscii( "\";\"" ).Append( aTemp ).AppendAscii( "\";\"" );
1309 const_cast< SvNumberformat* >( pEntry )->GetOutputString( 0.0, aTemp, &pColor );
1310 aFormatStr.Append( aTemp ).Append( '"' );
1311 }
1312 else
1313 {
1314 LanguageType eLang = pEntry->GetLanguage();
1315 if( eLang != LANGUAGE_ENGLISH_US )
1316 {
1317 xub_StrLen nCheckPos;
1318 short nType = NUMBERFORMAT_DEFINED;
1319 sal_uInt32 nKey;
1320 String aTemp( pEntry->GetFormatstring() );
1321 mxFormatter->PutandConvertEntry( aTemp, nCheckPos, nType, nKey, eLang, LANGUAGE_ENGLISH_US );
1322 DBG_ASSERT( nCheckPos == 0, "XclExpNumFmtBuffer::WriteFormatRecord - format code not convertible" );
1323 pEntry = mxFormatter->GetEntry( nKey );
1324 }
1325
1326 aFormatStr = pEntry->GetMappedFormatstring( *mpKeywordTable, *mxFormatter->GetLocaleData() );
1327 if( aFormatStr.EqualsAscii( "Standard" ) )
1328 aFormatStr.AssignAscii( "General" );
1329 }
1330 }
1331 else
1332 {
1333 DBG_ERRORFILE( "XclExpNumFmtBuffer::WriteFormatRecord - format not found" );
1334 aFormatStr.AssignAscii( "General" );
1335 }
1336
1337 return aFormatStr;
1338 }
1339
1340 // XF, STYLE record - Cell formatting =========================================
1341
FillFromItemSet(const SfxItemSet & rItemSet,bool bStyle)1342 bool XclExpCellProt::FillFromItemSet( const SfxItemSet& rItemSet, bool bStyle )
1343 {
1344 const ScProtectionAttr& rProtItem = GETITEM( rItemSet, ScProtectionAttr, ATTR_PROTECTION );
1345 mbLocked = rProtItem.GetProtection();
1346 mbHidden = rProtItem.GetHideFormula() || rProtItem.GetHideCell();
1347 return ScfTools::CheckItem( rItemSet, ATTR_PROTECTION, bStyle );
1348 }
1349
1350 #if 0
1351 void XclExpCellProt::FillToXF2( sal_uInt8& rnNumFmt ) const
1352 {
1353 ::set_flag( rnNumFmt, EXC_XF2_LOCKED, mbLocked );
1354 ::set_flag( rnNumFmt, EXC_XF2_HIDDEN, mbHidden );
1355 }
1356 #endif
1357
FillToXF3(sal_uInt16 & rnProt) const1358 void XclExpCellProt::FillToXF3( sal_uInt16& rnProt ) const
1359 {
1360 ::set_flag( rnProt, EXC_XF_LOCKED, mbLocked );
1361 ::set_flag( rnProt, EXC_XF_HIDDEN, mbHidden );
1362 }
1363
SaveXml(XclExpXmlStream & rStrm) const1364 void XclExpCellProt::SaveXml( XclExpXmlStream& rStrm ) const
1365 {
1366 rStrm.GetCurrentStream()->singleElement( XML_protection,
1367 XML_locked, XclXmlUtils::ToPsz( mbLocked ),
1368 XML_hidden, XclXmlUtils::ToPsz( mbHidden ),
1369 FSEND );
1370 }
1371
1372 // ----------------------------------------------------------------------------
1373
FillFromItemSet(const SfxItemSet & rItemSet,bool bForceLineBreak,XclBiff eBiff,bool bStyle)1374 bool XclExpCellAlign::FillFromItemSet(
1375 const SfxItemSet& rItemSet, bool bForceLineBreak, XclBiff eBiff, bool bStyle )
1376 {
1377 bool bUsed = false;
1378
1379 switch( eBiff )
1380 {
1381 // ALL 'case's - run through!
1382
1383 case EXC_BIFF8: // attributes new in BIFF8
1384 {
1385 // text indent
1386 long nTmpIndent = GETITEMVALUE( rItemSet, SfxUInt16Item, ATTR_INDENT, sal_Int32 );
1387 (nTmpIndent += 100) /= 200; // 1 Excel unit == 10 pt == 200 twips
1388 mnIndent = limit_cast< sal_uInt8 >( nTmpIndent, 0, 15 );
1389 bUsed |= ScfTools::CheckItem( rItemSet, ATTR_INDENT, bStyle );
1390
1391 // shrink to fit
1392 mbShrink = GETITEMVALUE( rItemSet, SfxBoolItem, ATTR_SHRINKTOFIT, sal_Bool );
1393 bUsed |= ScfTools::CheckItem( rItemSet, ATTR_SHRINKTOFIT, bStyle );
1394
1395 // CTL text direction
1396 SetScFrameDir( GETITEMVALUE( rItemSet, SvxFrameDirectionItem, ATTR_WRITINGDIR, SvxFrameDirection ) );
1397 bUsed |= ScfTools::CheckItem( rItemSet, ATTR_WRITINGDIR, bStyle );
1398 }
1399
1400 case EXC_BIFF5: // attributes new in BIFF5
1401 case EXC_BIFF4: // attributes new in BIFF4
1402 {
1403 // vertical alignment
1404 SetScVerAlign( GETITEMVALUE( rItemSet, SvxVerJustifyItem, ATTR_VER_JUSTIFY, SvxCellVerJustify ) );
1405 bUsed |= ScfTools::CheckItem( rItemSet, ATTR_VER_JUSTIFY, bStyle );
1406
1407 // stacked/rotation
1408 bool bStacked = GETITEMVALUE( rItemSet, SfxBoolItem, ATTR_STACKED, sal_Bool );
1409 bUsed |= ScfTools::CheckItem( rItemSet, ATTR_STACKED, bStyle );
1410 if( bStacked )
1411 {
1412 mnRotation = EXC_ROT_STACKED;
1413 }
1414 else
1415 {
1416 // rotation
1417 sal_Int32 nScRot = GETITEMVALUE( rItemSet, SfxInt32Item, ATTR_ROTATE_VALUE, sal_Int32 );
1418 mnRotation = XclTools::GetXclRotation( nScRot );
1419 bUsed |= ScfTools::CheckItem( rItemSet, ATTR_ROTATE_VALUE, bStyle );
1420 }
1421 mnOrient = XclTools::GetXclOrientFromRot( mnRotation );
1422 }
1423
1424 case EXC_BIFF3: // attributes new in BIFF3
1425 {
1426 // text wrap
1427 mbLineBreak = bForceLineBreak || GETITEMBOOL( rItemSet, ATTR_LINEBREAK );
1428 bUsed |= bForceLineBreak || ScfTools::CheckItem( rItemSet, ATTR_LINEBREAK, bStyle );
1429 }
1430
1431 case EXC_BIFF2: // attributes new in BIFF2
1432 {
1433 // horizontal alignment
1434 SetScHorAlign( GETITEMVALUE( rItemSet, SvxHorJustifyItem, ATTR_HOR_JUSTIFY, SvxCellHorJustify ) );
1435 bUsed |= ScfTools::CheckItem( rItemSet, ATTR_HOR_JUSTIFY, bStyle );
1436 }
1437
1438 break;
1439 default: DBG_ERROR_BIFF();
1440 }
1441
1442 return bUsed;
1443 }
1444
1445 #if 0
1446 void XclExpCellAlign::FillToXF2( sal_uInt8& rnFlags ) const
1447 {
1448 ::insert_value( rnFlags, mnHorAlign, 0, 3 );
1449 }
1450
1451 void XclExpCellAlign::FillToXF3( sal_uInt16& rnAlign ) const
1452 {
1453 ::insert_value( rnAlign, mnHorAlign, 0, 3 );
1454 ::set_flag( rnAlign, EXC_XF_LINEBREAK, mbLineBreak );
1455 }
1456
1457 void XclExpCellAlign::FillToXF4( sal_uInt16& rnAlign ) const
1458 {
1459 FillToXF3( rnAlign );
1460 ::insert_value( rnAlign, mnVerAlign, 4, 2 );
1461 ::insert_value( rnAlign, mnOrient, 6, 2 );
1462 }
1463 #endif
1464
FillToXF5(sal_uInt16 & rnAlign) const1465 void XclExpCellAlign::FillToXF5( sal_uInt16& rnAlign ) const
1466 {
1467 ::insert_value( rnAlign, mnHorAlign, 0, 3 );
1468 ::set_flag( rnAlign, EXC_XF_LINEBREAK, mbLineBreak );
1469 ::insert_value( rnAlign, mnVerAlign, 4, 3 );
1470 ::insert_value( rnAlign, mnOrient, 8, 2 );
1471 }
1472
FillToXF8(sal_uInt16 & rnAlign,sal_uInt16 & rnMiscAttrib) const1473 void XclExpCellAlign::FillToXF8( sal_uInt16& rnAlign, sal_uInt16& rnMiscAttrib ) const
1474 {
1475 ::insert_value( rnAlign, mnHorAlign, 0, 3 );
1476 ::set_flag( rnAlign, EXC_XF_LINEBREAK, mbLineBreak );
1477 ::insert_value( rnAlign, mnVerAlign, 4, 3 );
1478 ::insert_value( rnAlign, mnRotation, 8, 8 );
1479 ::insert_value( rnMiscAttrib, mnIndent, 0, 4 );
1480 ::set_flag( rnMiscAttrib, EXC_XF8_SHRINK, mbShrink );
1481 ::insert_value( rnMiscAttrib, mnTextDir, 6, 2 );
1482 }
1483
ToHorizontalAlignment(sal_uInt8 nHorAlign)1484 static const char* ToHorizontalAlignment( sal_uInt8 nHorAlign )
1485 {
1486 switch( nHorAlign )
1487 {
1488 case EXC_XF_HOR_GENERAL: return "general";
1489 case EXC_XF_HOR_LEFT: return "left";
1490 case EXC_XF_HOR_CENTER: return "center";
1491 case EXC_XF_HOR_RIGHT: return "right";
1492 case EXC_XF_HOR_FILL: return "fill";
1493 case EXC_XF_HOR_JUSTIFY: return "justify";
1494 case EXC_XF_HOR_CENTER_AS: return "centerContinuous";
1495 case EXC_XF_HOR_DISTRIB: return "distributed";
1496 }
1497 return "*unknown*";
1498 }
1499
ToVerticalAlignment(sal_uInt8 nVerAlign)1500 static const char* ToVerticalAlignment( sal_uInt8 nVerAlign )
1501 {
1502 switch( nVerAlign )
1503 {
1504 case EXC_XF_VER_TOP: return "top";
1505 case EXC_XF_VER_CENTER: return "center";
1506 case EXC_XF_VER_BOTTOM: return "bottom";
1507 case EXC_XF_VER_JUSTIFY: return "justify";
1508 case EXC_XF_VER_DISTRIB: return "distributed";
1509 }
1510 return "*unknown*";
1511 }
1512
SaveXml(XclExpXmlStream & rStrm) const1513 void XclExpCellAlign::SaveXml( XclExpXmlStream& rStrm ) const
1514 {
1515 rStrm.GetCurrentStream()->singleElement( XML_alignment,
1516 XML_horizontal, ToHorizontalAlignment( mnHorAlign ),
1517 XML_vertical, ToVerticalAlignment( mnVerAlign ),
1518 XML_textRotation, OString::valueOf( (sal_Int32) mnRotation ).getStr(),
1519 XML_wrapText, XclXmlUtils::ToPsz( mbLineBreak ),
1520 XML_indent, OString::valueOf( (sal_Int32) mnIndent ).getStr(),
1521 // OOXTODO: XML_relativeIndent, mnIndent?
1522 // OOXTODO: XML_justifyLastLine,
1523 XML_shrinkToFit, XclXmlUtils::ToPsz( mbShrink ),
1524 // OOXTODO: XML_readingOrder,
1525 FSEND );
1526 }
1527
1528 // ----------------------------------------------------------------------------
1529
1530 namespace {
1531
lclGetBorderLine(sal_uInt8 & rnXclLine,sal_uInt32 & rnColorId,const SvxBorderLine * pLine,XclExpPalette & rPalette,XclBiff eBiff)1532 void lclGetBorderLine(
1533 sal_uInt8& rnXclLine, sal_uInt32& rnColorId,
1534 const SvxBorderLine* pLine, XclExpPalette& rPalette, XclBiff eBiff )
1535 {
1536 rnXclLine = EXC_LINE_NONE;
1537 if( pLine )
1538 {
1539 sal_uInt16 nOuterWidth = pLine->GetOutWidth();
1540 sal_uInt16 nDistance = pLine->GetDistance();
1541 if( nDistance > 0 )
1542 rnXclLine = EXC_LINE_DOUBLE;
1543 else if( nOuterWidth > DEF_LINE_WIDTH_2 )
1544 rnXclLine = EXC_LINE_THICK;
1545 else if( nOuterWidth > DEF_LINE_WIDTH_1 )
1546 rnXclLine = EXC_LINE_MEDIUM;
1547 else if( nOuterWidth > DEF_LINE_WIDTH_0 )
1548 rnXclLine = EXC_LINE_THIN;
1549 else if( nOuterWidth > 0 )
1550 rnXclLine = EXC_LINE_HAIR;
1551 else
1552 rnXclLine = EXC_LINE_NONE;
1553 }
1554 if( (eBiff == EXC_BIFF2) && (rnXclLine != EXC_LINE_NONE) )
1555 rnXclLine = EXC_LINE_THIN;
1556
1557 rnColorId = (pLine && (rnXclLine != EXC_LINE_NONE)) ?
1558 rPalette.InsertColor( pLine->GetColor(), EXC_COLOR_CELLBORDER ) :
1559 XclExpPalette::GetColorIdFromIndex( 0 );
1560 }
1561
1562 } // namespace
1563
1564 // ----------------------------------------------------------------------------
1565
XclExpCellBorder()1566 XclExpCellBorder::XclExpCellBorder() :
1567 mnLeftColorId( XclExpPalette::GetColorIdFromIndex( mnLeftColor ) ),
1568 mnRightColorId( XclExpPalette::GetColorIdFromIndex( mnRightColor ) ),
1569 mnTopColorId( XclExpPalette::GetColorIdFromIndex( mnTopColor ) ),
1570 mnBottomColorId( XclExpPalette::GetColorIdFromIndex( mnBottomColor ) ),
1571 mnDiagColorId( XclExpPalette::GetColorIdFromIndex( mnDiagColor ) )
1572 {
1573 }
1574
FillFromItemSet(const SfxItemSet & rItemSet,XclExpPalette & rPalette,XclBiff eBiff,bool bStyle)1575 bool XclExpCellBorder::FillFromItemSet(
1576 const SfxItemSet& rItemSet, XclExpPalette& rPalette, XclBiff eBiff, bool bStyle )
1577 {
1578 bool bUsed = false;
1579
1580 switch( eBiff )
1581 {
1582 // ALL 'case's - run through!
1583
1584 case EXC_BIFF8: // attributes new in BIFF8
1585 {
1586 const SvxLineItem& rTLBRItem = GETITEM( rItemSet, SvxLineItem, ATTR_BORDER_TLBR );
1587 sal_uInt8 nTLBRLine;
1588 sal_uInt32 nTLBRColorId;
1589 lclGetBorderLine( nTLBRLine, nTLBRColorId, rTLBRItem.GetLine(), rPalette, eBiff );
1590 mbDiagTLtoBR = (nTLBRLine != EXC_LINE_NONE);
1591
1592 const SvxLineItem& rBLTRItem = GETITEM( rItemSet, SvxLineItem, ATTR_BORDER_BLTR );
1593 sal_uInt8 nBLTRLine;
1594 sal_uInt32 nBLTRColorId;
1595 lclGetBorderLine( nBLTRLine, nBLTRColorId, rBLTRItem.GetLine(), rPalette, eBiff );
1596 mbDiagBLtoTR = (nBLTRLine != EXC_LINE_NONE);
1597
1598 if( ::ScHasPriority( rTLBRItem.GetLine(), rBLTRItem.GetLine() ) )
1599 {
1600 mnDiagLine = nTLBRLine;
1601 mnDiagColorId = nTLBRColorId;
1602 }
1603 else
1604 {
1605 mnDiagLine = nBLTRLine;
1606 mnDiagColorId = nBLTRColorId;
1607 }
1608
1609 bUsed |= ScfTools::CheckItem( rItemSet, ATTR_BORDER_TLBR, bStyle ) ||
1610 ScfTools::CheckItem( rItemSet, ATTR_BORDER_BLTR, bStyle );
1611 }
1612
1613 case EXC_BIFF5:
1614 case EXC_BIFF4:
1615 case EXC_BIFF3:
1616 case EXC_BIFF2:
1617 {
1618 const SvxBoxItem& rBoxItem = GETITEM( rItemSet, SvxBoxItem, ATTR_BORDER );
1619 lclGetBorderLine( mnLeftLine, mnLeftColorId, rBoxItem.GetLeft(), rPalette, eBiff );
1620 lclGetBorderLine( mnRightLine, mnRightColorId, rBoxItem.GetRight(), rPalette, eBiff );
1621 lclGetBorderLine( mnTopLine, mnTopColorId, rBoxItem.GetTop(), rPalette, eBiff );
1622 lclGetBorderLine( mnBottomLine, mnBottomColorId, rBoxItem.GetBottom(), rPalette, eBiff );
1623 bUsed |= ScfTools::CheckItem( rItemSet, ATTR_BORDER, bStyle );
1624 }
1625
1626 break;
1627 default: DBG_ERROR_BIFF();
1628 }
1629
1630 return bUsed;
1631 }
1632
SetFinalColors(const XclExpPalette & rPalette)1633 void XclExpCellBorder::SetFinalColors( const XclExpPalette& rPalette )
1634 {
1635 mnLeftColor = rPalette.GetColorIndex( mnLeftColorId );
1636 mnRightColor = rPalette.GetColorIndex( mnRightColorId );
1637 mnTopColor = rPalette.GetColorIndex( mnTopColorId );
1638 mnBottomColor = rPalette.GetColorIndex( mnBottomColorId );
1639 mnDiagColor = rPalette.GetColorIndex( mnDiagColorId );
1640 }
1641
1642 #if 0
1643 void XclExpCellBorder::FillToXF2( sal_uInt8& rnFlags ) const
1644 {
1645 ::set_flag( rnFlags, EXC_XF2_LEFTLINE, mnLeftLine != EXC_LINE_NONE );
1646 ::set_flag( rnFlags, EXC_XF2_RIGHTLINE, mnRightLine != EXC_LINE_NONE );
1647 ::set_flag( rnFlags, EXC_XF2_TOPLINE, mnTopLine != EXC_LINE_NONE );
1648 ::set_flag( rnFlags, EXC_XF2_BOTTOMLINE, mnBottomLine != EXC_LINE_NONE );
1649 }
1650
1651 void XclExpCellBorder::FillToXF3( sal_uInt32& rnBorder ) const
1652 {
1653 ::insert_value( rnBorder, mnTopLine, 0, 3 );
1654 ::insert_value( rnBorder, mnLeftLine, 8, 3 );
1655 ::insert_value( rnBorder, mnBottomLine, 16, 3 );
1656 ::insert_value( rnBorder, mnRightLine, 24, 3 );
1657 ::insert_value( rnBorder, mnTopColor, 3, 5 );
1658 ::insert_value( rnBorder, mnLeftColor, 11, 5 );
1659 ::insert_value( rnBorder, mnBottomColor, 19, 5 );
1660 ::insert_value( rnBorder, mnRightColor, 27, 5 );
1661 }
1662 #endif
1663
FillToXF5(sal_uInt32 & rnBorder,sal_uInt32 & rnArea) const1664 void XclExpCellBorder::FillToXF5( sal_uInt32& rnBorder, sal_uInt32& rnArea ) const
1665 {
1666 ::insert_value( rnBorder, mnTopLine, 0, 3 );
1667 ::insert_value( rnBorder, mnLeftLine, 3, 3 );
1668 ::insert_value( rnArea, mnBottomLine, 22, 3 );
1669 ::insert_value( rnBorder, mnRightLine, 6, 3 );
1670 ::insert_value( rnBorder, mnTopColor, 9, 7 );
1671 ::insert_value( rnBorder, mnLeftColor, 16, 7 );
1672 ::insert_value( rnArea, mnBottomColor, 25, 7 );
1673 ::insert_value( rnBorder, mnRightColor, 23, 7 );
1674 }
1675
FillToXF8(sal_uInt32 & rnBorder1,sal_uInt32 & rnBorder2) const1676 void XclExpCellBorder::FillToXF8( sal_uInt32& rnBorder1, sal_uInt32& rnBorder2 ) const
1677 {
1678 ::insert_value( rnBorder1, mnLeftLine, 0, 4 );
1679 ::insert_value( rnBorder1, mnRightLine, 4, 4 );
1680 ::insert_value( rnBorder1, mnTopLine, 8, 4 );
1681 ::insert_value( rnBorder1, mnBottomLine, 12, 4 );
1682 ::insert_value( rnBorder1, mnLeftColor, 16, 7 );
1683 ::insert_value( rnBorder1, mnRightColor, 23, 7 );
1684 ::insert_value( rnBorder2, mnTopColor, 0, 7 );
1685 ::insert_value( rnBorder2, mnBottomColor, 7, 7 );
1686 ::insert_value( rnBorder2, mnDiagColor, 14, 7 );
1687 ::insert_value( rnBorder2, mnDiagLine, 21, 4 );
1688 ::set_flag( rnBorder1, EXC_XF_DIAGONAL_TL_TO_BR, mbDiagTLtoBR );
1689 ::set_flag( rnBorder1, EXC_XF_DIAGONAL_BL_TO_TR, mbDiagBLtoTR );
1690 }
1691
FillToCF8(sal_uInt16 & rnLine,sal_uInt32 & rnColor) const1692 void XclExpCellBorder::FillToCF8( sal_uInt16& rnLine, sal_uInt32& rnColor ) const
1693 {
1694 ::insert_value( rnLine, mnLeftLine, 0, 4 );
1695 ::insert_value( rnLine, mnRightLine, 4, 4 );
1696 ::insert_value( rnLine, mnTopLine, 8, 4 );
1697 ::insert_value( rnLine, mnBottomLine, 12, 4 );
1698 ::insert_value( rnColor, mnLeftColor, 0, 7 );
1699 ::insert_value( rnColor, mnRightColor, 7, 7 );
1700 ::insert_value( rnColor, mnTopColor, 16, 7 );
1701 ::insert_value( rnColor, mnBottomColor, 23, 7 );
1702 }
1703
ToLineStyle(sal_uInt8 nLineStyle)1704 static const char* ToLineStyle( sal_uInt8 nLineStyle )
1705 {
1706 switch( nLineStyle )
1707 {
1708 case EXC_LINE_NONE: return "none";
1709 case EXC_LINE_THIN: return "thin";
1710 case EXC_LINE_MEDIUM: return "medium";
1711 case EXC_LINE_THICK: return "thick";
1712 case EXC_LINE_DOUBLE: return "double";
1713 case EXC_LINE_HAIR: return "hair";
1714 }
1715 return "*unknown*";
1716 }
1717
lcl_WriteBorder(XclExpXmlStream & rStrm,sal_Int32 nElement,sal_uInt8 nLineStyle,const Color & rColor)1718 static void lcl_WriteBorder( XclExpXmlStream& rStrm, sal_Int32 nElement, sal_uInt8 nLineStyle, const Color& rColor )
1719 {
1720 sax_fastparser::FSHelperPtr& rStyleSheet = rStrm.GetCurrentStream();
1721 if( nLineStyle == EXC_LINE_NONE )
1722 rStyleSheet->singleElement( nElement, FSEND );
1723 else if( rColor == Color( 0, 0, 0, 0 ) )
1724 rStyleSheet->singleElement( nElement,
1725 XML_style, ToLineStyle( nLineStyle ),
1726 FSEND );
1727 else
1728 {
1729 rStyleSheet->startElement( nElement,
1730 XML_style, ToLineStyle( nLineStyle ),
1731 FSEND );
1732 rStyleSheet->singleElement( XML_color,
1733 XML_rgb, XclXmlUtils::ToOString( rColor ).getStr(),
1734 FSEND );
1735 rStyleSheet->endElement( nElement );
1736 }
1737 }
1738
SaveXml(XclExpXmlStream & rStrm) const1739 void XclExpCellBorder::SaveXml( XclExpXmlStream& rStrm ) const
1740 {
1741 sax_fastparser::FSHelperPtr& rStyleSheet = rStrm.GetCurrentStream();
1742
1743 XclExpPalette& rPalette = rStrm.GetRoot().GetPalette();
1744
1745 rStyleSheet->startElement( XML_border,
1746 XML_diagonalUp, XclXmlUtils::ToPsz( mbDiagBLtoTR ),
1747 XML_diagonalDown, XclXmlUtils::ToPsz( mbDiagTLtoBR ),
1748 // OOXTODO: XML_outline,
1749 FSEND );
1750 lcl_WriteBorder( rStrm, XML_left, mnLeftLine, rPalette.GetColor( mnLeftColor ) );
1751 lcl_WriteBorder( rStrm, XML_right, mnRightLine, rPalette.GetColor( mnRightColor ) );
1752 lcl_WriteBorder( rStrm, XML_top, mnTopLine, rPalette.GetColor( mnTopColor ) );
1753 lcl_WriteBorder( rStrm, XML_bottom, mnBottomLine, rPalette.GetColor( mnBottomColor ) );
1754 lcl_WriteBorder( rStrm, XML_diagonal, mnDiagLine, rPalette.GetColor( mnDiagColor ) );
1755 // OOXTODO: XML_vertical, XML_horizontal
1756 rStyleSheet->endElement( XML_border );
1757 }
1758
1759 // ----------------------------------------------------------------------------
1760
XclExpCellArea()1761 XclExpCellArea::XclExpCellArea() :
1762 mnForeColorId( XclExpPalette::GetColorIdFromIndex( mnForeColor ) ),
1763 mnBackColorId( XclExpPalette::GetColorIdFromIndex( mnBackColor ) )
1764 {
1765 }
1766
FillFromItemSet(const SfxItemSet & rItemSet,XclExpPalette & rPalette,bool bStyle)1767 bool XclExpCellArea::FillFromItemSet( const SfxItemSet& rItemSet, XclExpPalette& rPalette, bool bStyle )
1768 {
1769 const SvxBrushItem& rBrushItem = GETITEM( rItemSet, SvxBrushItem, ATTR_BACKGROUND );
1770 if( rBrushItem.GetColor().GetTransparency() )
1771 {
1772 mnPattern = EXC_PATT_NONE;
1773 mnForeColorId = XclExpPalette::GetColorIdFromIndex( EXC_COLOR_WINDOWTEXT );
1774 mnBackColorId = XclExpPalette::GetColorIdFromIndex( EXC_COLOR_WINDOWBACK );
1775 }
1776 else
1777 {
1778 mnPattern = EXC_PATT_SOLID;
1779 mnForeColorId = rPalette.InsertColor( rBrushItem.GetColor(), EXC_COLOR_CELLAREA );
1780 mnBackColorId = XclExpPalette::GetColorIdFromIndex( EXC_COLOR_WINDOWTEXT );
1781 }
1782 return ScfTools::CheckItem( rItemSet, ATTR_BACKGROUND, bStyle );
1783 }
1784
SetFinalColors(const XclExpPalette & rPalette)1785 void XclExpCellArea::SetFinalColors( const XclExpPalette& rPalette )
1786 {
1787 rPalette.GetMixedColors( mnForeColor, mnBackColor, mnPattern, mnForeColorId, mnBackColorId );
1788 }
1789
1790 #if 0
1791 void XclExpCellArea::FillToXF2( sal_uInt8& rnFlags ) const
1792 {
1793 ::set_flag( rnFlags, EXC_XF2_BACKGROUND, mnPattern != EXC_PATT_NONE );
1794 }
1795
1796 void XclExpCellArea::FillToXF3( sal_uInt16& rnArea ) const
1797 {
1798 ::insert_value( rnArea, mnPattern, 0, 6 );
1799 ::insert_value( rnArea, mnForeColor, 6, 5 );
1800 ::insert_value( rnArea, mnBackColor, 11, 5 );
1801 }
1802 #endif
1803
FillToXF5(sal_uInt32 & rnArea) const1804 void XclExpCellArea::FillToXF5( sal_uInt32& rnArea ) const
1805 {
1806 ::insert_value( rnArea, mnPattern, 16, 6 );
1807 ::insert_value( rnArea, mnForeColor, 0, 7 );
1808 ::insert_value( rnArea, mnBackColor, 7, 7 );
1809 }
1810
FillToXF8(sal_uInt32 & rnBorder2,sal_uInt16 & rnArea) const1811 void XclExpCellArea::FillToXF8( sal_uInt32& rnBorder2, sal_uInt16& rnArea ) const
1812 {
1813 ::insert_value( rnBorder2, mnPattern, 26, 6 );
1814 ::insert_value( rnArea, mnForeColor, 0, 7 );
1815 ::insert_value( rnArea, mnBackColor, 7, 7 );
1816 }
1817
FillToCF8(sal_uInt16 & rnPattern,sal_uInt16 & rnColor) const1818 void XclExpCellArea::FillToCF8( sal_uInt16& rnPattern, sal_uInt16& rnColor ) const
1819 {
1820 XclCellArea aTmp( *this );
1821 if( !aTmp.IsTransparent() && (aTmp.mnBackColor == EXC_COLOR_WINDOWTEXT) )
1822 aTmp.mnBackColor = 0;
1823 if( aTmp.mnPattern == EXC_PATT_SOLID )
1824 ::std::swap( aTmp.mnForeColor, aTmp.mnBackColor );
1825 ::insert_value( rnColor, aTmp.mnForeColor, 0, 7 );
1826 ::insert_value( rnColor, aTmp.mnBackColor, 7, 7 );
1827 ::insert_value( rnPattern, aTmp.mnPattern, 10, 6 );
1828 }
1829
ToPatternType(sal_uInt8 nPattern)1830 static const char* ToPatternType( sal_uInt8 nPattern )
1831 {
1832 switch( nPattern )
1833 {
1834 case EXC_PATT_NONE: return "none";
1835 case EXC_PATT_SOLID: return "solid";
1836 case EXC_PATT_50_PERC: return "mediumGray";
1837 case EXC_PATT_75_PERC: return "darkGray";
1838 case EXC_PATT_25_PERC: return "lightGray";
1839 case EXC_PATT_12_5_PERC: return "gray125";
1840 case EXC_PATT_6_25_PERC: return "gray0625";
1841 }
1842 return "*unknown*";
1843 }
1844
SaveXml(XclExpXmlStream & rStrm) const1845 void XclExpCellArea::SaveXml( XclExpXmlStream& rStrm ) const
1846 {
1847 sax_fastparser::FSHelperPtr& rStyleSheet = rStrm.GetCurrentStream();
1848 rStyleSheet->startElement( XML_fill,
1849 FSEND );
1850
1851 // OOXTODO: XML_gradientFill
1852
1853 XclExpPalette& rPalette = rStrm.GetRoot().GetPalette();
1854
1855 if( mnPattern == EXC_PATT_NONE || ( mnForeColor == 0 && mnBackColor == 0 ) )
1856 rStyleSheet->singleElement( XML_patternFill,
1857 XML_patternType, ToPatternType( mnPattern ),
1858 FSEND );
1859 else
1860 {
1861 rStyleSheet->startElement( XML_patternFill,
1862 XML_patternType, ToPatternType( mnPattern ),
1863 FSEND );
1864 rStyleSheet->singleElement( XML_fgColor,
1865 XML_rgb, XclXmlUtils::ToOString( rPalette.GetColor( mnForeColor ) ).getStr(),
1866 FSEND );
1867 rStyleSheet->singleElement( XML_bgColor,
1868 XML_rgb, XclXmlUtils::ToOString( rPalette.GetColor( mnBackColor ) ).getStr(),
1869 FSEND );
1870 rStyleSheet->endElement( XML_patternFill );
1871 }
1872
1873 rStyleSheet->endElement( XML_fill );
1874 }
1875
1876 // ----------------------------------------------------------------------------
1877
XclExpXFId()1878 XclExpXFId::XclExpXFId() :
1879 mnXFId( XclExpXFBuffer::GetDefCellXFId() ),
1880 mnXFIndex( EXC_XF_DEFAULTCELL )
1881 {
1882 }
1883
XclExpXFId(sal_uInt32 nXFId)1884 XclExpXFId::XclExpXFId( sal_uInt32 nXFId ) :
1885 mnXFId( nXFId ),
1886 mnXFIndex( EXC_XF_DEFAULTCELL )
1887 {
1888 }
1889
ConvertXFIndex(const XclExpRoot & rRoot)1890 void XclExpXFId::ConvertXFIndex( const XclExpRoot& rRoot )
1891 {
1892 mnXFIndex = rRoot.GetXFBuffer().GetXFIndex( mnXFId );
1893 }
1894
1895 // ----------------------------------------------------------------------------
1896
XclExpXF(const XclExpRoot & rRoot,const ScPatternAttr & rPattern,sal_Int16 nScript,sal_uLong nForceScNumFmt,sal_uInt16 nForceXclFont,bool bForceLineBreak)1897 XclExpXF::XclExpXF(
1898 const XclExpRoot& rRoot, const ScPatternAttr& rPattern, sal_Int16 nScript,
1899 sal_uLong nForceScNumFmt, sal_uInt16 nForceXclFont, bool bForceLineBreak )
1900 : XclXFBase(true),
1901 XclExpRecord(),
1902 XclExpRoot(rRoot),
1903 mpItemSet(0),
1904 maProtection(),
1905 maAlignment(),
1906 maBorder(),
1907 maArea(),
1908 mnParentXFId(),
1909 mnScNumFmt(),
1910 mnXclFont(),
1911 mnXclNumFmt(),
1912 mnBorderId(),
1913 mnFillId(),
1914 mnIndexInXFList(0)
1915 {
1916 mnParentXFId = GetXFBuffer().InsertStyle( rPattern.GetStyleSheet() );
1917 Init( rPattern.GetItemSet(), nScript, nForceScNumFmt, nForceXclFont, bForceLineBreak, false );
1918 }
1919
XclExpXF(const XclExpRoot & rRoot,const SfxStyleSheetBase & rStyleSheet)1920 XclExpXF::XclExpXF( const XclExpRoot& rRoot, const SfxStyleSheetBase& rStyleSheet )
1921 : XclXFBase(false),
1922 XclExpRecord(),
1923 XclExpRoot(rRoot),
1924 mpItemSet(0),
1925 maProtection(),
1926 maAlignment(),
1927 maBorder(),
1928 maArea(),
1929 mnParentXFId(XclExpXFBuffer::GetXFIdFromIndex(EXC_XF_STYLEPARENT)),
1930 mnScNumFmt(),
1931 mnXclFont(),
1932 mnXclNumFmt(),
1933 mnBorderId(),
1934 mnFillId(),
1935 mnIndexInXFList(0)
1936 {
1937 bool bDefStyle = (rStyleSheet.GetName() == ScGlobal::GetRscString( STR_STYLENAME_STANDARD ));
1938 sal_Int16 nScript = bDefStyle ? GetDefApiScript() : ::com::sun::star::i18n::ScriptType::WEAK;
1939 Init( const_cast< SfxStyleSheetBase& >( rStyleSheet ).GetItemSet(), nScript,
1940 NUMBERFORMAT_ENTRY_NOT_FOUND, EXC_FONT_NOTFOUND, false, bDefStyle );
1941 }
1942
XclExpXF(const XclExpRoot & rRoot,bool bCellXF)1943 XclExpXF::XclExpXF( const XclExpRoot& rRoot, bool bCellXF )
1944 : XclXFBase(bCellXF),
1945 XclExpRecord(),
1946 XclExpRoot(rRoot),
1947 mpItemSet(0),
1948 maProtection(),
1949 maAlignment(),
1950 maBorder(),
1951 maArea(),
1952 mnParentXFId(XclExpXFBuffer::GetXFIdFromIndex(EXC_XF_STYLEPARENT)),
1953 mnScNumFmt(),
1954 mnXclFont(),
1955 mnXclNumFmt(),
1956 mnBorderId(),
1957 mnFillId(),
1958 mnIndexInXFList(0)
1959 {
1960 InitDefault();
1961 }
1962
Equals(const ScPatternAttr & rPattern,sal_uLong nForceScNumFmt,sal_uInt16 nForceXclFont,bool bForceLineBreak) const1963 bool XclExpXF::Equals( const ScPatternAttr& rPattern,
1964 sal_uLong nForceScNumFmt, sal_uInt16 nForceXclFont, bool bForceLineBreak ) const
1965 {
1966 return IsCellXF() && (mpItemSet == &rPattern.GetItemSet()) &&
1967 (!bForceLineBreak || maAlignment.mbLineBreak) &&
1968 ((nForceScNumFmt == NUMBERFORMAT_ENTRY_NOT_FOUND) || (mnScNumFmt == nForceScNumFmt)) &&
1969 ((nForceXclFont == EXC_FONT_NOTFOUND) || (mnXclFont == nForceXclFont));
1970 }
1971
Equals(const SfxStyleSheetBase & rStyleSheet) const1972 bool XclExpXF::Equals( const SfxStyleSheetBase& rStyleSheet ) const
1973 {
1974 return IsStyleXF() && (mpItemSet == &const_cast< SfxStyleSheetBase& >( rStyleSheet ).GetItemSet());
1975 }
1976
SetFinalColors()1977 void XclExpXF::SetFinalColors()
1978 {
1979 maBorder.SetFinalColors( GetPalette() );
1980 maArea.SetFinalColors( GetPalette() );
1981 }
1982
Equals(const XclExpXF & rCmpXF) const1983 bool XclExpXF::Equals( const XclExpXF& rCmpXF ) const
1984 {
1985 return XclXFBase::Equals( rCmpXF ) &&
1986 (maProtection == rCmpXF.maProtection) && (maAlignment == rCmpXF.maAlignment) &&
1987 (maBorder == rCmpXF.maBorder) && (maArea == rCmpXF.maArea) &&
1988 (mnXclFont == rCmpXF.mnXclFont) && (mnXclNumFmt == rCmpXF.mnXclNumFmt) &&
1989 (mnParentXFId == rCmpXF.mnParentXFId);
1990 }
1991
InitDefault()1992 void XclExpXF::InitDefault()
1993 {
1994 SetRecHeader( EXC_ID5_XF, (GetBiff() == EXC_BIFF8) ? 20 : 16 );
1995 mpItemSet = 0;
1996 mnScNumFmt = NUMBERFORMAT_ENTRY_NOT_FOUND;
1997 mnXclFont = mnXclNumFmt = 0;
1998 }
1999
Init(const SfxItemSet & rItemSet,sal_Int16 nScript,sal_uLong nForceScNumFmt,sal_uInt16 nForceXclFont,bool bForceLineBreak,bool bDefStyle)2000 void XclExpXF::Init( const SfxItemSet& rItemSet, sal_Int16 nScript,
2001 sal_uLong nForceScNumFmt, sal_uInt16 nForceXclFont, bool bForceLineBreak, bool bDefStyle )
2002 {
2003 InitDefault();
2004 mpItemSet = &rItemSet;
2005
2006 // cell protection
2007 mbProtUsed = maProtection.FillFromItemSet( rItemSet, IsStyleXF() );
2008
2009 // font
2010 if( nForceXclFont == EXC_FONT_NOTFOUND )
2011 {
2012 mnXclFont = GetFontBuffer().Insert( rItemSet, nScript, EXC_COLOR_CELLTEXT, bDefStyle );
2013 mbFontUsed = XclExpFontHelper::CheckItems( GetRoot(), rItemSet, nScript, IsStyleXF() );
2014 }
2015 else
2016 {
2017 mnXclFont = nForceXclFont;
2018 mbFontUsed = true;
2019 }
2020
2021 // number format
2022 mnScNumFmt = (nForceScNumFmt == NUMBERFORMAT_ENTRY_NOT_FOUND) ?
2023 GETITEMVALUE( rItemSet, SfxUInt32Item, ATTR_VALUE_FORMAT, sal_uLong ) : nForceScNumFmt;
2024 mnXclNumFmt = GetNumFmtBuffer().Insert( mnScNumFmt );
2025 mbFmtUsed = ScfTools::CheckItem( rItemSet, ATTR_VALUE_FORMAT, IsStyleXF() );
2026
2027 // alignment
2028 mbAlignUsed = maAlignment.FillFromItemSet( rItemSet, bForceLineBreak, GetBiff(), IsStyleXF() );
2029
2030 // cell border
2031 mbBorderUsed = maBorder.FillFromItemSet( rItemSet, GetPalette(), GetBiff(), IsStyleXF() );
2032
2033 // background area
2034 mbAreaUsed = maArea.FillFromItemSet( rItemSet, GetPalette(), IsStyleXF() );
2035
2036 // set all b***Used flags to true in "Default"/"Normal" style
2037 if( bDefStyle )
2038 SetAllUsedFlags( true );
2039 }
2040
GetUsedFlags() const2041 sal_uInt8 XclExpXF::GetUsedFlags() const
2042 {
2043 sal_uInt8 nUsedFlags = 0;
2044 /* In cell XFs a set bit means a used attribute, in style XFs a cleared bit.
2045 "mbCellXF == mb***Used" evaluates to correct value in cell and style XFs. */
2046 ::set_flag( nUsedFlags, EXC_XF_DIFF_PROT, mbCellXF == mbProtUsed );
2047 ::set_flag( nUsedFlags, EXC_XF_DIFF_FONT, mbCellXF == mbFontUsed );
2048 ::set_flag( nUsedFlags, EXC_XF_DIFF_VALFMT, mbCellXF == mbFmtUsed );
2049 ::set_flag( nUsedFlags, EXC_XF_DIFF_ALIGN, mbCellXF == mbAlignUsed );
2050 ::set_flag( nUsedFlags, EXC_XF_DIFF_BORDER, mbCellXF == mbBorderUsed );
2051 ::set_flag( nUsedFlags, EXC_XF_DIFF_AREA, mbCellXF == mbAreaUsed );
2052 return nUsedFlags;
2053 }
2054
WriteBody5(XclExpStream & rStrm)2055 void XclExpXF::WriteBody5( XclExpStream& rStrm )
2056 {
2057 sal_uInt16 nTypeProt = 0, nAlign = 0;
2058 sal_uInt32 nArea = 0, nBorder = 0;
2059
2060 ::set_flag( nTypeProt, EXC_XF_STYLE, IsStyleXF() );
2061 ::insert_value( nTypeProt, mnParent, 4, 12 );
2062 ::insert_value( nAlign, GetUsedFlags(), 10, 6 );
2063
2064 maProtection.FillToXF3( nTypeProt );
2065 maAlignment.FillToXF5( nAlign );
2066 maBorder.FillToXF5( nBorder, nArea );
2067 maArea.FillToXF5( nArea );
2068
2069 rStrm << mnXclFont << mnXclNumFmt << nTypeProt << nAlign << nArea << nBorder;
2070 }
2071
WriteBody8(XclExpStream & rStrm)2072 void XclExpXF::WriteBody8( XclExpStream& rStrm )
2073 {
2074 sal_uInt16 nTypeProt = 0, nAlign = 0, nMiscAttrib = 0, nArea = 0;
2075 sal_uInt32 nBorder1 = 0, nBorder2 = 0;
2076
2077 ::set_flag( nTypeProt, EXC_XF_STYLE, IsStyleXF() );
2078 ::insert_value( nTypeProt, mnParent, 4, 12 );
2079 ::insert_value( nMiscAttrib, GetUsedFlags(), 10, 6 );
2080
2081 maProtection.FillToXF3( nTypeProt );
2082 maAlignment.FillToXF8( nAlign, nMiscAttrib );
2083 maBorder.FillToXF8( nBorder1, nBorder2 );
2084 maArea.FillToXF8( nBorder2, nArea );
2085
2086 rStrm << mnXclFont << mnXclNumFmt << nTypeProt << nAlign << nMiscAttrib << nBorder1 << nBorder2 << nArea;
2087 }
2088
WriteBody(XclExpStream & rStrm)2089 void XclExpXF::WriteBody( XclExpStream& rStrm )
2090 {
2091 XclExpXFId aParentId( mnParentXFId );
2092 aParentId.ConvertXFIndex( GetRoot() );
2093 mnParent = aParentId.mnXFIndex;
2094 switch( GetBiff() )
2095 {
2096 case EXC_BIFF5: WriteBody5( rStrm ); break;
2097 case EXC_BIFF8: WriteBody8( rStrm ); break;
2098 default: DBG_ERROR_BIFF();
2099 }
2100 }
2101
SetXmlIds(sal_uInt32 nBorderId,sal_uInt32 nFillId)2102 void XclExpXF::SetXmlIds( sal_uInt32 nBorderId, sal_uInt32 nFillId )
2103 {
2104 mnBorderId = nBorderId;
2105 mnFillId = nFillId;
2106 }
2107
SaveXml(XclExpXmlStream & rStrm)2108 void XclExpXF::SaveXml( XclExpXmlStream& rStrm )
2109 {
2110 sax_fastparser::FSHelperPtr& rStyleSheet = rStrm.GetCurrentStream();
2111
2112 sal_Int32 nXfId = 0;
2113 if( IsCellXF() )
2114 {
2115 sal_uInt16 nXFIndex = rStrm.GetRoot().GetXFBuffer().GetXFIndex( mnParentXFId );
2116 nXfId = rStrm.GetRoot().GetXFBuffer().GetXmlStyleIndex( nXFIndex );
2117 }
2118
2119 rStyleSheet->startElement( XML_xf,
2120 XML_numFmtId, OString::valueOf( (sal_Int32) mnXclNumFmt ).getStr(),
2121 XML_fontId, OString::valueOf( (sal_Int32) mnXclFont ).getStr(),
2122 XML_fillId, OString::valueOf( (sal_Int32) mnFillId ).getStr(),
2123 XML_borderId, OString::valueOf( (sal_Int32) mnBorderId ).getStr(),
2124 XML_xfId, IsStyleXF() ? NULL : OString::valueOf( nXfId ).getStr(),
2125 // OOXTODO: XML_quotePrefix,
2126 // OOXTODO: XML_pivotButton,
2127 // OOXTODO: XML_applyNumberFormat, ;
2128 XML_applyFont, XclXmlUtils::ToPsz( mbFontUsed ),
2129 // OOXTODO: XML_applyFill,
2130 XML_applyBorder, XclXmlUtils::ToPsz( mbBorderUsed ),
2131 XML_applyAlignment, XclXmlUtils::ToPsz( mbAlignUsed ),
2132 XML_applyProtection, XclXmlUtils::ToPsz( mbProtUsed ),
2133 FSEND );
2134 if( mbAlignUsed )
2135 maAlignment.SaveXml( rStrm );
2136 if( mbProtUsed )
2137 maProtection.SaveXml( rStrm );
2138 // OOXTODO: XML_extLst
2139 rStyleSheet->endElement( XML_xf );
2140 }
2141
2142 // ----------------------------------------------------------------------------
2143
XclExpDefaultXF(const XclExpRoot & rRoot,bool bCellXF)2144 XclExpDefaultXF::XclExpDefaultXF( const XclExpRoot& rRoot, bool bCellXF ) :
2145 XclExpXF( rRoot, bCellXF )
2146 {
2147 }
2148
2149 //UNUSED2008-05 void XclExpDefaultXF::SetParent( sal_uInt32 nParentXFId )
2150 //UNUSED2008-05 {
2151 //UNUSED2008-05 DBG_ASSERT( IsCellXF(), "XclExpDefaultXF::SetParent - not allowed in style XFs" );
2152 //UNUSED2008-05 if( IsCellXF() )
2153 //UNUSED2008-05 mnParentXFId = nParentXFId;
2154 //UNUSED2008-05 }
2155 //UNUSED2008-05
2156 //UNUSED2008-05 void XclExpDefaultXF::SetUsedFlags(
2157 //UNUSED2008-05 bool bProtUsed, bool bFontUsed, bool bFmtUsed,
2158 //UNUSED2008-05 bool bAlignUsed, bool bBorderUsed, bool bAreaUsed )
2159 //UNUSED2008-05 {
2160 //UNUSED2008-05 mbProtUsed = bProtUsed;
2161 //UNUSED2008-05 mbFontUsed = bFontUsed;
2162 //UNUSED2008-05 mbFmtUsed = bFmtUsed;
2163 //UNUSED2008-05 mbAlignUsed = bAlignUsed;
2164 //UNUSED2008-05 mbBorderUsed = bBorderUsed;
2165 //UNUSED2008-05 mbAreaUsed = bAreaUsed;
2166 //UNUSED2008-05 }
2167 //UNUSED2008-05
2168 //UNUSED2008-05 void XclExpDefaultXF::SetProtection( const XclExpCellProt& rProtection )
2169 //UNUSED2008-05 {
2170 //UNUSED2008-05 maProtection = rProtection;
2171 //UNUSED2008-05 mbProtUsed = true;
2172 //UNUSED2008-05 }
2173 //UNUSED2008-05
2174 //UNUSED2008-05 void XclExpDefaultXF::SetAlignment( const XclExpCellAlign& rAlignment )
2175 //UNUSED2008-05 {
2176 //UNUSED2008-05 maAlignment = rAlignment;
2177 //UNUSED2008-05 mbAlignUsed = true;
2178 //UNUSED2008-05 }
2179 //UNUSED2008-05
2180 //UNUSED2008-05 void XclExpDefaultXF::SetBorder( const XclExpCellBorder& rBorder )
2181 //UNUSED2008-05 {
2182 //UNUSED2008-05 maBorder = rBorder;
2183 //UNUSED2008-05 mbBorderUsed = true;
2184 //UNUSED2008-05 }
2185 //UNUSED2008-05
2186 //UNUSED2008-05 void XclExpDefaultXF::SetArea( const XclExpCellArea& rArea )
2187 //UNUSED2008-05 {
2188 //UNUSED2008-05 maArea = rArea;
2189 //UNUSED2008-05 mbAreaUsed = true;
2190 //UNUSED2008-05 }
2191
SetFont(sal_uInt16 nXclFont)2192 void XclExpDefaultXF::SetFont( sal_uInt16 nXclFont )
2193 {
2194 mnXclFont = nXclFont;
2195 mbFontUsed = true;
2196 }
2197
SetNumFmt(sal_uInt16 nXclNumFmt)2198 void XclExpDefaultXF::SetNumFmt( sal_uInt16 nXclNumFmt )
2199 {
2200 mnXclNumFmt = nXclNumFmt;
2201 mbFmtUsed = true;
2202 }
2203
2204 // ----------------------------------------------------------------------------
2205
XclExpStyle(sal_uInt32 nXFId,const String & rStyleName)2206 XclExpStyle::XclExpStyle( sal_uInt32 nXFId, const String& rStyleName ) :
2207 XclExpRecord( EXC_ID_STYLE, 4 ),
2208 maName( rStyleName ),
2209 maXFId( nXFId ),
2210 mnStyleId( EXC_STYLE_USERDEF ),
2211 mnLevel( EXC_STYLE_NOLEVEL )
2212 {
2213 DBG_ASSERT( maName.Len(), "XclExpStyle::XclExpStyle - empty style name" );
2214 #ifdef DBG_UTIL
2215 sal_uInt8 nStyleId, nLevel; // do not use members for debug tests
2216 DBG_ASSERT( !XclTools::GetBuiltInStyleId( nStyleId, nLevel, maName ),
2217 "XclExpStyle::XclExpStyle - this is a built-in style" );
2218 #endif
2219 }
2220
XclExpStyle(sal_uInt32 nXFId,sal_uInt8 nStyleId,sal_uInt8 nLevel)2221 XclExpStyle::XclExpStyle( sal_uInt32 nXFId, sal_uInt8 nStyleId, sal_uInt8 nLevel ) :
2222 XclExpRecord( EXC_ID_STYLE, 4 ),
2223 maXFId( nXFId ),
2224 mnStyleId( nStyleId ),
2225 mnLevel( nLevel )
2226 {
2227 }
2228
WriteBody(XclExpStream & rStrm)2229 void XclExpStyle::WriteBody( XclExpStream& rStrm )
2230 {
2231 maXFId.ConvertXFIndex( rStrm.GetRoot() );
2232 ::set_flag( maXFId.mnXFIndex, EXC_STYLE_BUILTIN, IsBuiltIn() );
2233 rStrm << maXFId.mnXFIndex;
2234
2235 if( IsBuiltIn() )
2236 {
2237 rStrm << mnStyleId << mnLevel;
2238 }
2239 else
2240 {
2241 XclExpString aNameEx;
2242 if( rStrm.GetRoot().GetBiff() == EXC_BIFF8 )
2243 aNameEx.Assign( maName );
2244 else
2245 aNameEx.AssignByte( maName, rStrm.GetRoot().GetTextEncoding(), EXC_STR_8BITLENGTH );
2246 rStrm << aNameEx;
2247 }
2248 }
2249
lcl_StyleNameFromId(sal_Int32 nStyleId)2250 static const char* lcl_StyleNameFromId( sal_Int32 nStyleId )
2251 {
2252 switch( nStyleId )
2253 {
2254 case 0: return "Normal";
2255 case 3: return "Comma";
2256 case 4: return "Currency";
2257 case 5: return "Percent";
2258 case 6: return "Comma [0]";
2259 case 7: return "Currency [0]";
2260 }
2261 return "*unknown*";
2262 }
2263
SaveXml(XclExpXmlStream & rStrm)2264 void XclExpStyle::SaveXml( XclExpXmlStream& rStrm )
2265 {
2266 OString sName;
2267 if( IsBuiltIn() )
2268 {
2269 sName = OString( lcl_StyleNameFromId( mnStyleId ) );
2270 }
2271 else
2272 sName = XclXmlUtils::ToOString( maName );
2273 sal_Int32 nXFId = rStrm.GetRoot().GetXFBuffer().GetXmlStyleIndex( maXFId.mnXFId );
2274 rStrm.GetCurrentStream()->singleElement( XML_cellStyle,
2275 XML_name, sName.getStr(),
2276 XML_xfId, OString::valueOf( nXFId ).getStr(),
2277 XML_builtinId, OString::valueOf( (sal_Int32) mnStyleId ).getStr(),
2278 // OOXTODO: XML_iLevel,
2279 // OOXTODO: XML_hidden,
2280 XML_customBuiltin, XclXmlUtils::ToPsz( ! IsBuiltIn() ),
2281 FSEND );
2282 // OOXTODO: XML_extLst
2283 }
2284
2285 // ----------------------------------------------------------------------------
2286
2287 namespace {
2288
2289 const sal_uInt32 EXC_XFLIST_INDEXBASE = 0xFFFE0000;
2290 /** Maximum count of XF records to store in the XF list (performance). */
2291 const sal_uInt32 EXC_XFLIST_HARDLIMIT = 256 * 1024;
2292
lclIsBuiltInStyle(const String & rStyleName)2293 bool lclIsBuiltInStyle( const String& rStyleName )
2294 {
2295 return
2296 XclTools::IsBuiltInStyleName( rStyleName ) ||
2297 XclTools::IsCondFormatStyleName( rStyleName );
2298 }
2299
2300 } // namespace
2301
2302 // ----------------------------------------------------------------------------
2303
XclExpBuiltInInfo()2304 XclExpXFBuffer::XclExpBuiltInInfo::XclExpBuiltInInfo() :
2305 mnStyleId( EXC_STYLE_USERDEF ),
2306 mnLevel( EXC_STYLE_NOLEVEL ),
2307 mbPredefined( true ),
2308 mbHasStyleRec( false )
2309 {
2310 }
2311
2312 // ----------------------------------------------------------------------------
2313
2314 /** Predicate for search algorithm. */
2315 struct XclExpBorderPred
2316 {
2317 const XclExpCellBorder&
2318 mrBorder;
XclExpBorderPredXclExpBorderPred2319 inline explicit XclExpBorderPred( const XclExpCellBorder& rBorder ) : mrBorder( rBorder ) {}
2320 bool operator()( const XclExpCellBorder& rBorder ) const;
2321 };
2322
operator ()(const XclExpCellBorder & rBorder) const2323 bool XclExpBorderPred::operator()( const XclExpCellBorder& rBorder ) const
2324 {
2325 return
2326 mrBorder.mnLeftColor == rBorder.mnLeftColor &&
2327 mrBorder.mnRightColor == rBorder.mnRightColor &&
2328 mrBorder.mnTopColor == rBorder.mnTopColor &&
2329 mrBorder.mnBottomColor == rBorder.mnBottomColor &&
2330 mrBorder.mnDiagColor == rBorder.mnDiagColor &&
2331 mrBorder.mnLeftLine == rBorder.mnLeftLine &&
2332 mrBorder.mnRightLine == rBorder.mnRightLine &&
2333 mrBorder.mnTopLine == rBorder.mnTopLine &&
2334 mrBorder.mnBottomLine == rBorder.mnBottomLine &&
2335 mrBorder.mnDiagLine == rBorder.mnDiagLine &&
2336 mrBorder.mbDiagTLtoBR == rBorder.mbDiagTLtoBR &&
2337 mrBorder.mbDiagBLtoTR == rBorder.mbDiagBLtoTR &&
2338 mrBorder.mnLeftColorId == rBorder.mnLeftColorId &&
2339 mrBorder.mnRightColorId == rBorder.mnRightColorId &&
2340 mrBorder.mnTopColorId == rBorder.mnTopColorId &&
2341 mrBorder.mnBottomColorId == rBorder.mnBottomColorId &&
2342 mrBorder.mnDiagColorId == rBorder.mnDiagColorId;
2343 }
2344
2345 struct XclExpFillPred
2346 {
2347 const XclExpCellArea&
2348 mrFill;
XclExpFillPredXclExpFillPred2349 inline explicit XclExpFillPred( const XclExpCellArea& rFill ) : mrFill( rFill ) {}
2350 bool operator()( const XclExpCellArea& rFill ) const;
2351 };
2352
operator ()(const XclExpCellArea & rFill) const2353 bool XclExpFillPred::operator()( const XclExpCellArea& rFill ) const
2354 {
2355 return
2356 mrFill.mnForeColor == rFill.mnForeColor &&
2357 mrFill.mnBackColor == rFill.mnBackColor &&
2358 mrFill.mnPattern == rFill.mnPattern &&
2359 mrFill.mnForeColorId == rFill.mnForeColorId &&
2360 mrFill.mnBackColorId == rFill.mnBackColorId;
2361 }
2362
2363 static bool XclExpXFBuffer_mbUseMultimapBuffer = true;
2364
XclExpXFBuffer(const XclExpRoot & rRoot)2365 XclExpXFBuffer::XclExpXFBuffer( const XclExpRoot& rRoot )
2366 : XclExpRecordBase(),
2367 XclExpRoot(rRoot),
2368 maXFList(),
2369 maStyleList(),
2370 maBuiltInMap(),
2371 maXFIndexVec(),
2372 maStyleIndexes(),
2373 maCellIndexes(),
2374 maSortedXFList(),
2375 maBorders(),
2376 maFills(),
2377 maXclExpXFMap()
2378 {
2379 }
2380
Initialize()2381 void XclExpXFBuffer::Initialize()
2382 {
2383 InsertDefaultRecords();
2384 InsertUserStyles();
2385 }
2386
Insert(const ScPatternAttr * pPattern,sal_Int16 nScript)2387 sal_uInt32 XclExpXFBuffer::Insert( const ScPatternAttr* pPattern, sal_Int16 nScript )
2388 {
2389 return InsertCellXF( pPattern, nScript, NUMBERFORMAT_ENTRY_NOT_FOUND, EXC_FONT_NOTFOUND, false );
2390 }
2391
InsertWithFont(const ScPatternAttr * pPattern,sal_Int16 nScript,sal_uInt16 nForceXclFont,bool bForceLineBreak)2392 sal_uInt32 XclExpXFBuffer::InsertWithFont( const ScPatternAttr* pPattern, sal_Int16 nScript,
2393 sal_uInt16 nForceXclFont, bool bForceLineBreak )
2394 {
2395 return InsertCellXF( pPattern, nScript, NUMBERFORMAT_ENTRY_NOT_FOUND, nForceXclFont, bForceLineBreak );
2396 }
2397
InsertWithNumFmt(const ScPatternAttr * pPattern,sal_Int16 nScript,sal_uLong nForceScNumFmt,bool bForceLineBreak)2398 sal_uInt32 XclExpXFBuffer::InsertWithNumFmt( const ScPatternAttr* pPattern, sal_Int16 nScript, sal_uLong nForceScNumFmt, bool bForceLineBreak )
2399 {
2400 return InsertCellXF( pPattern, nScript, nForceScNumFmt, EXC_FONT_NOTFOUND, bForceLineBreak );
2401 }
2402
InsertStyle(const SfxStyleSheetBase * pStyleSheet)2403 sal_uInt32 XclExpXFBuffer::InsertStyle( const SfxStyleSheetBase* pStyleSheet )
2404 {
2405 return pStyleSheet ? InsertStyleXF( *pStyleSheet ) : GetXFIdFromIndex( EXC_XF_DEFAULTSTYLE );
2406 }
2407
GetXFIdFromIndex(sal_uInt16 nXFIndex)2408 sal_uInt32 XclExpXFBuffer::GetXFIdFromIndex( sal_uInt16 nXFIndex )
2409 {
2410 return EXC_XFLIST_INDEXBASE | nXFIndex;
2411 }
2412
GetDefCellXFId()2413 sal_uInt32 XclExpXFBuffer::GetDefCellXFId()
2414 {
2415 return GetXFIdFromIndex( EXC_XF_DEFAULTCELL );
2416 }
2417
GetXFById(sal_uInt32 nXFId) const2418 const XclExpXF* XclExpXFBuffer::GetXFById( sal_uInt32 nXFId ) const
2419 {
2420 return maXFList.GetRecord( nXFId ).get();
2421 }
2422
Finalize()2423 void XclExpXFBuffer::Finalize()
2424 {
2425 for( size_t nPos = 0, nSize = maXFList.GetSize(); nPos < nSize; ++nPos )
2426 maXFList.GetRecord( nPos )->SetFinalColors();
2427
2428 sal_uInt32 nTotalCount = static_cast< sal_uInt32 >( maXFList.GetSize() );
2429 sal_uInt32 nId;
2430 maXFIndexVec.resize( nTotalCount, EXC_XF_DEFAULTCELL );
2431 maStyleIndexes.resize( nTotalCount, EXC_XF_DEFAULTCELL );
2432 maCellIndexes.resize( nTotalCount, EXC_XF_DEFAULTCELL );
2433
2434 XclExpBuiltInMap::const_iterator aBuiltInEnd = maBuiltInMap.end();
2435 /* nMaxBuiltInXFId used to decide faster whether an XF record is
2436 user-defined. If the current XF ID is greater than this value,
2437 maBuiltInMap doesn't need to be searched. */
2438 sal_uInt32 nMaxBuiltInXFId = maBuiltInMap.empty() ? 0 : maBuiltInMap.rbegin()->first;
2439
2440 // *** map all built-in XF records (cell and style) *** -------------------
2441
2442 // do not change XF order -> std::map<> iterates elements in ascending order
2443 for( XclExpBuiltInMap::const_iterator aIt = maBuiltInMap.begin(); aIt != aBuiltInEnd; ++aIt )
2444 AppendXFIndex( aIt->first );
2445
2446 // *** insert all user-defined style XF records, without reduce *** -------
2447
2448 sal_uInt32 nStyleXFCount = 0; // counts up to EXC_XF_MAXSTYLECOUNT limit
2449
2450 for( nId = 0; nId < nTotalCount; ++nId )
2451 {
2452 XclExpXFRef xXF = maXFList.GetRecord( nId );
2453 if( xXF->IsStyleXF() && ((nId > nMaxBuiltInXFId) || (maBuiltInMap.find( nId ) == aBuiltInEnd)) )
2454 {
2455 if( nStyleXFCount < EXC_XF_MAXSTYLECOUNT )
2456 {
2457 // maximum count of styles not reached
2458 AppendXFIndex( nId );
2459 ++nStyleXFCount;
2460 }
2461 else
2462 {
2463 /* Maximum count of styles reached - do not append more
2464 pointers to XFs; use default style XF instead; do not break
2465 the loop to initialize all maXFIndexVec elements. */
2466 maXFIndexVec[ nId ] = EXC_XF_DEFAULTSTYLE;
2467 }
2468 }
2469 }
2470
2471 // *** insert all cell XF records *** -------------------------------------
2472
2473 // start position to search for equal inserted XF records
2474 size_t nSearchStart = maSortedXFList.GetSize();
2475
2476 // break the loop if XF limit reached - maXFIndexVec is already initialized with default index
2477 XclExpXFRef xDefCellXF = maXFList.GetRecord( EXC_XF_DEFAULTCELL );
2478 for( nId = 0; (nId < nTotalCount) && (maSortedXFList.GetSize() < EXC_XF_MAXCOUNT); ++nId )
2479 {
2480 XclExpXFRef xXF = maXFList.GetRecord( nId );
2481 if( xXF->IsCellXF() && ((nId > nMaxBuiltInXFId) || (maBuiltInMap.find( nId ) == aBuiltInEnd)) )
2482 {
2483 // try to find an XF record equal to *xXF, which is already inserted
2484 sal_uInt16 nFoundIndex = EXC_XF_NOTFOUND;
2485
2486 // first try if it is equal to the default cell XF
2487 if( xDefCellXF->Equals( *xXF ) )
2488 {
2489 nFoundIndex = EXC_XF_DEFAULTCELL;
2490 }
2491 else for( size_t nSearchPos = nSearchStart, nSearchEnd = maSortedXFList.GetSize();
2492 (nSearchPos < nSearchEnd) && (nFoundIndex == EXC_XF_NOTFOUND); ++nSearchPos )
2493 {
2494 if( maSortedXFList.GetRecord( nSearchPos )->Equals( *xXF ) )
2495 nFoundIndex = static_cast< sal_uInt16 >( nSearchPos );
2496 }
2497
2498 if( nFoundIndex != EXC_XF_NOTFOUND )
2499 // equal XF already in the list, use its resulting XF index
2500 maXFIndexVec[ nId ] = nFoundIndex;
2501 else
2502 AppendXFIndex( nId );
2503 }
2504 }
2505
2506 sal_uInt16 nXmlStyleIndex = 0;
2507 sal_uInt16 nXmlCellIndex = 0;
2508
2509 size_t nXFCount = maSortedXFList.GetSize();
2510 for( size_t i = 0; i < nXFCount; ++i )
2511 {
2512 XclExpXFList::RecordRefType xXF = maSortedXFList.GetRecord( i );
2513 if( xXF->IsStyleXF() )
2514 maStyleIndexes[ i ] = nXmlStyleIndex++;
2515 else
2516 maCellIndexes[ i ] = nXmlCellIndex++;
2517 }
2518 }
2519
GetXFIndex(sal_uInt32 nXFId) const2520 sal_uInt16 XclExpXFBuffer::GetXFIndex( sal_uInt32 nXFId ) const
2521 {
2522 sal_uInt16 nXFIndex = EXC_XF_DEFAULTSTYLE;
2523 if( nXFId >= EXC_XFLIST_INDEXBASE )
2524 nXFIndex = static_cast< sal_uInt16 >( nXFId & ~EXC_XFLIST_INDEXBASE );
2525 else if( nXFId < maXFIndexVec.size() )
2526 nXFIndex = maXFIndexVec[ nXFId ];
2527 return nXFIndex;
2528 }
2529
GetXmlStyleIndex(sal_uInt32 nXFIndex) const2530 sal_Int32 XclExpXFBuffer::GetXmlStyleIndex( sal_uInt32 nXFIndex ) const
2531 {
2532 DBG_ASSERT( nXFIndex < maStyleIndexes.size(), "XclExpXFBuffer::GetXmlStyleIndex - invalid index!" );
2533 if( nXFIndex > maStyleIndexes.size() )
2534 return 0; // should be caught/debugged via above assert; return "valid" index.
2535 return maStyleIndexes[ nXFIndex ];
2536 }
2537
GetXmlCellIndex(sal_uInt32 nXFIndex) const2538 sal_Int32 XclExpXFBuffer::GetXmlCellIndex( sal_uInt32 nXFIndex ) const
2539 {
2540 DBG_ASSERT( nXFIndex < maCellIndexes.size(), "XclExpXFBuffer::GetXmlStyleIndex - invalid index!" );
2541 if( nXFIndex > maCellIndexes.size() )
2542 return 0; // should be caught/debugged via above assert; return "valid" index.
2543 return maCellIndexes[ nXFIndex ];
2544 }
2545
Save(XclExpStream & rStrm)2546 void XclExpXFBuffer::Save( XclExpStream& rStrm )
2547 {
2548 // save all XF records contained in the maSortedXFList vector (sorted by XF index)
2549 maSortedXFList.Save( rStrm );
2550 // save all STYLE records
2551 maStyleList.Save( rStrm );
2552 }
2553
lcl_GetCellCounts(const XclExpRecordList<XclExpXF> & rXFList,sal_Int32 & rCells,sal_Int32 & rStyles)2554 static void lcl_GetCellCounts( const XclExpRecordList< XclExpXF >& rXFList, sal_Int32& rCells, sal_Int32& rStyles )
2555 {
2556 rCells = 0;
2557 rStyles = 0;
2558 size_t nXFCount = rXFList.GetSize();
2559 for( size_t i = 0; i < nXFCount; ++i )
2560 {
2561 XclExpRecordList< XclExpXF >::RecordRefType xXF = rXFList.GetRecord( i );
2562 if( xXF->IsCellXF() )
2563 ++rCells;
2564 else if( xXF->IsStyleXF() )
2565 ++rStyles;
2566 }
2567 }
2568
SaveXml(XclExpXmlStream & rStrm)2569 void XclExpXFBuffer::SaveXml( XclExpXmlStream& rStrm )
2570 {
2571 sax_fastparser::FSHelperPtr& rStyleSheet = rStrm.GetCurrentStream();
2572
2573 rStyleSheet->startElement( XML_fills,
2574 XML_count, OString::valueOf( (sal_Int32) maFills.size() ).getStr(),
2575 FSEND );
2576 for( XclExpFillList::iterator aIt = maFills.begin(), aEnd = maFills.end();
2577 aIt != aEnd; ++aIt )
2578 {
2579 aIt->SaveXml( rStrm );
2580 }
2581 rStyleSheet->endElement( XML_fills );
2582
2583 rStyleSheet->startElement( XML_borders,
2584 XML_count, OString::valueOf( (sal_Int32) maBorders.size() ).getStr(),
2585 FSEND );
2586 for( XclExpBorderList::iterator aIt = maBorders.begin(), aEnd = maBorders.end();
2587 aIt != aEnd; ++aIt )
2588 {
2589 aIt->SaveXml( rStrm );
2590 }
2591 rStyleSheet->endElement( XML_borders );
2592
2593 // save all XF records contained in the maSortedXFList vector (sorted by XF index)
2594 sal_Int32 nCells, nStyles;
2595 lcl_GetCellCounts( maSortedXFList, nCells, nStyles );
2596
2597 if( nStyles > 0 )
2598 {
2599 rStyleSheet->startElement( XML_cellStyleXfs,
2600 XML_count, OString::valueOf( nStyles ).getStr(),
2601 FSEND );
2602 size_t nXFCount = maSortedXFList.GetSize();
2603 for( size_t i = 0; i < nXFCount; ++i )
2604 {
2605 XclExpXFList::RecordRefType xXF = maSortedXFList.GetRecord( i );
2606 if( ! xXF->IsStyleXF() )
2607 continue;
2608 SaveXFXml( rStrm, *xXF );
2609 }
2610 rStyleSheet->endElement( XML_cellStyleXfs );
2611 }
2612
2613 if( nCells > 0 )
2614 {
2615 rStyleSheet->startElement( XML_cellXfs,
2616 XML_count, OString::valueOf( nCells ).getStr(),
2617 FSEND );
2618 size_t nXFCount = maSortedXFList.GetSize();
2619 for( size_t i = 0; i < nXFCount; ++i )
2620 {
2621 XclExpXFList::RecordRefType xXF = maSortedXFList.GetRecord( i );
2622 if( ! xXF->IsCellXF() )
2623 continue;
2624 SaveXFXml( rStrm, *xXF );
2625 }
2626 rStyleSheet->endElement( XML_cellXfs );
2627 }
2628
2629 // save all STYLE records
2630 rStyleSheet->startElement( XML_cellStyles,
2631 XML_count, OString::valueOf( (sal_Int32) maStyleList.GetSize() ).getStr(),
2632 FSEND );
2633 maStyleList.SaveXml( rStrm );
2634 rStyleSheet->endElement( XML_cellStyles );
2635 }
2636
SaveXFXml(XclExpXmlStream & rStrm,XclExpXF & rXF)2637 void XclExpXFBuffer::SaveXFXml( XclExpXmlStream& rStrm, XclExpXF& rXF )
2638 {
2639 XclExpBorderList::iterator aBorderPos =
2640 std::find_if( maBorders.begin(), maBorders.end(), XclExpBorderPred( rXF.GetBorderData() ) );
2641 DBG_ASSERT( aBorderPos != maBorders.end(), "XclExpXFBuffer::SaveXml - Invalid @borderId!" );
2642 XclExpFillList::iterator aFillPos =
2643 std::find_if( maFills.begin(), maFills.end(), XclExpFillPred( rXF.GetAreaData() ) );
2644 DBG_ASSERT( aFillPos != maFills.end(), "XclExpXFBuffer::SaveXml - Invalid @fillId!" );
2645
2646 sal_Int32 nBorderId = 0, nFillId = 0;
2647 if( aBorderPos != maBorders.end() )
2648 nBorderId = std::distance( maBorders.begin(), aBorderPos );
2649 if( aFillPos != maFills.end() )
2650 nFillId = std::distance( maFills.begin(), aFillPos );
2651
2652 rXF.SetXmlIds( nBorderId, nFillId );
2653 rXF.SaveXml( rStrm );
2654 }
2655
impAddMissingValuesFromXFListToXclExpXFMap()2656 void XclExpXFBuffer::impAddMissingValuesFromXFListToXclExpXFMap()
2657 {
2658 for(size_t nPos(maXclExpXFMap.size()); nPos < maXFList.GetSize(); ++nPos)
2659 {
2660 XclExpXF* pValue = maXFList.GetRecord(nPos).get();
2661
2662 if(pValue)
2663 {
2664 const SfxItemSet* pKey = maXFList.GetRecord(nPos)->getItemSet();
2665
2666 maXclExpXFMap.insert(std::pair< const SfxItemSet*, XclExpXF* >(pKey, pValue));
2667 pValue->setIndexInXFList(nPos);
2668 }
2669 else
2670 {
2671 OSL_ENSURE(false, "maXFList has empty entries (!)");
2672 }
2673 }
2674 }
2675
FindXF(const ScPatternAttr & rPattern,sal_uLong nForceScNumFmt,sal_uInt16 nForceXclFont,bool bForceLineBreak) const2676 sal_uInt32 XclExpXFBuffer::FindXF(const ScPatternAttr& rPattern, sal_uLong nForceScNumFmt, sal_uInt16 nForceXclFont, bool bForceLineBreak) const
2677 {
2678 // define return value
2679 sal_uInt32 nXFId(EXC_XFID_NOTFOUND);
2680
2681 if(XclExpXFBuffer_mbUseMultimapBuffer)
2682 {
2683 // add values from maXFList which are not yet in maXclExpXFMap
2684 const_cast< XclExpXFBuffer* >(this)->impAddMissingValuesFromXFListToXclExpXFMap();
2685
2686 // get the full range for the pattern set
2687 typedef std::multimap< const SfxItemSet*, XclExpXF* >::const_iterator CIT;
2688 typedef std::pair< CIT, CIT > Range;
2689 const SfxItemSet* pPatternSet = &(rPattern.GetItemSet());
2690 const Range range(maXclExpXFMap.equal_range(pPatternSet));
2691
2692 // iterate over evtl. multiple candidates using the pattern set
2693 for(CIT ite(range.first); ite != range.second; ++ite)
2694 {
2695 XclExpXF* pIte = ite->second;
2696
2697 if(pIte->Equals(rPattern, nForceScNumFmt, nForceXclFont, bForceLineBreak))
2698 {
2699 nXFId = pIte->getIndexInXFList();
2700 break;
2701 }
2702 }
2703 }
2704 else
2705 {
2706 // old, unbuffered implementation
2707 for( size_t nPos = 0, nSize = maXFList.GetSize(); nPos < nSize; ++nPos )
2708 if( maXFList.GetRecord( nPos )->Equals( rPattern, nForceScNumFmt, nForceXclFont, bForceLineBreak ) )
2709 return static_cast< sal_uInt32 >( nPos );
2710 }
2711
2712 return nXFId;
2713 }
2714
FindXF(const SfxStyleSheetBase & rStyleSheet) const2715 sal_uInt32 XclExpXFBuffer::FindXF( const SfxStyleSheetBase& rStyleSheet ) const
2716 {
2717 if(XclExpXFBuffer_mbUseMultimapBuffer)
2718 {
2719 // add values from maXFList which are not yet in maXclExpXFMap
2720 const_cast< XclExpXFBuffer* >(this)->impAddMissingValuesFromXFListToXclExpXFMap();
2721
2722 // find entry with given ItemSet (by StyleSheet)
2723 const SfxItemSet& rItemSet = const_cast< SfxStyleSheetBase& >(rStyleSheet).GetItemSet();
2724 typedef std::multimap< const SfxItemSet*, XclExpXF* >::const_iterator CIT;
2725 const CIT aFound(maXclExpXFMap.find(&rItemSet));
2726
2727 if(aFound != maXclExpXFMap.end())
2728 {
2729 return aFound->second->getIndexInXFList();
2730 }
2731 }
2732 else
2733 {
2734 // old, unbuffered implementation
2735 for( size_t nPos = 0, nSize = maXFList.GetSize(); nPos < nSize; ++nPos )
2736 if( maXFList.GetRecord( nPos )->Equals( rStyleSheet ) )
2737 return static_cast< sal_uInt32 >( nPos );
2738 }
2739
2740 return EXC_XFID_NOTFOUND;
2741 }
2742
FindBuiltInXF(sal_uInt8 nStyleId,sal_uInt8 nLevel) const2743 sal_uInt32 XclExpXFBuffer::FindBuiltInXF( sal_uInt8 nStyleId, sal_uInt8 nLevel ) const
2744 {
2745 for( XclExpBuiltInMap::const_iterator aIt = maBuiltInMap.begin(), aEnd = maBuiltInMap.end(); aIt != aEnd; ++aIt )
2746 if( (aIt->second.mnStyleId == nStyleId) && (aIt->second.mnLevel == nLevel) )
2747 return aIt->first;
2748 return EXC_XFID_NOTFOUND;
2749 }
2750
InsertCellXF(const ScPatternAttr * pPattern,sal_Int16 nScript,sal_uLong nForceScNumFmt,sal_uInt16 nForceXclFont,bool bForceLineBreak)2751 sal_uInt32 XclExpXFBuffer::InsertCellXF( const ScPatternAttr* pPattern, sal_Int16 nScript,
2752 sal_uLong nForceScNumFmt, sal_uInt16 nForceXclFont, bool bForceLineBreak )
2753 {
2754 const ScPatternAttr* pDefPattern = GetDoc().GetDefPattern();
2755 if( !pPattern )
2756 pPattern = pDefPattern;
2757
2758 // special handling for default cell formatting
2759 if( (pPattern == pDefPattern) && !bForceLineBreak &&
2760 (nForceScNumFmt == NUMBERFORMAT_ENTRY_NOT_FOUND) &&
2761 (nForceXclFont == EXC_FONT_NOTFOUND) )
2762 {
2763 // Is it the first try to insert the default cell format?
2764 bool& rbPredefined = maBuiltInMap[ EXC_XF_DEFAULTCELL ].mbPredefined;
2765 if( rbPredefined )
2766 {
2767 // replace default cell pattern
2768 XclExpXFRef xNewXF( new XclExpXF( GetRoot(), *pPattern, nScript ) );
2769 maXFList.ReplaceRecord( xNewXF, EXC_XF_DEFAULTCELL );
2770
2771 // need to clear the multimap buffer to force reinsertin of the new element
2772 if(XclExpXFBuffer_mbUseMultimapBuffer)
2773 {
2774 maXclExpXFMap.clear();
2775 }
2776
2777 rbPredefined = false;
2778 }
2779 return GetDefCellXFId();
2780 }
2781
2782 sal_uInt32 nXFId = FindXF( *pPattern, nForceScNumFmt, nForceXclFont, bForceLineBreak );
2783 if( nXFId == EXC_XFID_NOTFOUND )
2784 {
2785 // not found - insert new cell XF
2786 if( maXFList.GetSize() < EXC_XFLIST_HARDLIMIT )
2787 {
2788 maXFList.AppendNewRecord( new XclExpXF(
2789 GetRoot(), *pPattern, nScript, nForceScNumFmt, nForceXclFont, bForceLineBreak ) );
2790 // do not set nXFId before the AppendNewRecord() call - it may insert 2 XFs (style+cell)
2791 nXFId = static_cast< sal_uInt32 >( maXFList.GetSize() - 1 );
2792 }
2793 else
2794 {
2795 // list full - fall back to default cell XF
2796 nXFId = GetDefCellXFId();
2797 }
2798 }
2799 return nXFId;
2800 }
2801
InsertStyleXF(const SfxStyleSheetBase & rStyleSheet)2802 sal_uInt32 XclExpXFBuffer::InsertStyleXF( const SfxStyleSheetBase& rStyleSheet )
2803 {
2804 // *** try, if it is a built-in style - create new XF or replace existing predefined XF ***
2805
2806 sal_uInt8 nStyleId, nLevel;
2807 if( XclTools::GetBuiltInStyleId( nStyleId, nLevel, rStyleSheet.GetName() ) )
2808 {
2809 // try to find the built-in XF record (if already created in InsertDefaultRecords())
2810 sal_uInt32 nXFId = FindBuiltInXF( nStyleId, nLevel );
2811 if( nXFId == EXC_XFID_NOTFOUND )
2812 {
2813 // built-in style XF not yet created - do it now
2814 XclExpXFRef xXF( new XclExpXF( GetRoot(), rStyleSheet ) );
2815 nXFId = AppendBuiltInXFWithStyle( xXF, nStyleId, nLevel );
2816 // this new XF record is not predefined
2817 maBuiltInMap[ nXFId ].mbPredefined = false;
2818 }
2819 else
2820 {
2821 DBG_ASSERT( maXFList.HasRecord( nXFId ), "XclExpXFBuffer::InsertStyleXF - built-in XF not found" );
2822 // XF record still predefined? -> Replace with real XF
2823 bool& rbPredefined = maBuiltInMap[ nXFId ].mbPredefined;
2824 if( rbPredefined )
2825 {
2826 // replace predefined built-in style (ReplaceRecord() deletes old record)
2827 maXFList.ReplaceRecord( XclExpXFRef( new XclExpXF( GetRoot(), rStyleSheet ) ), nXFId );
2828
2829 // need to clear the multimap buffer to force reinsertin of the new element
2830 if(XclExpXFBuffer_mbUseMultimapBuffer)
2831 {
2832 maXclExpXFMap.clear();
2833 }
2834
2835 rbPredefined = false;
2836 }
2837 }
2838
2839 // STYLE already inserted? (may be not, i.e. for RowLevel/ColLevel or Hyperlink styles)
2840 bool& rbHasStyleRec = maBuiltInMap[ nXFId ].mbHasStyleRec;
2841 if( !rbHasStyleRec )
2842 {
2843 maStyleList.AppendNewRecord( new XclExpStyle( nXFId, nStyleId, nLevel ) );
2844 rbHasStyleRec = true;
2845 }
2846
2847 return nXFId;
2848 }
2849
2850 // *** try to find the XF record of a user-defined style ***
2851
2852 sal_uInt32 nXFId = FindXF( rStyleSheet );
2853 if( nXFId == EXC_XFID_NOTFOUND )
2854 {
2855 // not found - insert new style XF and STYLE
2856 nXFId = static_cast< sal_uInt32 >( maXFList.GetSize() );
2857 if( nXFId < EXC_XFLIST_HARDLIMIT )
2858 {
2859 maXFList.AppendNewRecord( new XclExpXF( GetRoot(), rStyleSheet ) );
2860 // create the STYLE record
2861 if( rStyleSheet.GetName().Len() )
2862 maStyleList.AppendNewRecord( new XclExpStyle( nXFId, rStyleSheet.GetName() ) );
2863 }
2864 else
2865 // list full - fall back to default style XF
2866 nXFId = GetXFIdFromIndex( EXC_XF_DEFAULTSTYLE );
2867 }
2868 return nXFId;
2869 }
2870
InsertUserStyles()2871 void XclExpXFBuffer::InsertUserStyles()
2872 {
2873 SfxStyleSheetIterator aStyleIter( GetDoc().GetStyleSheetPool(), SFX_STYLE_FAMILY_PARA );
2874 for( SfxStyleSheetBase* pStyleSheet = aStyleIter.First(); pStyleSheet; pStyleSheet = aStyleIter.Next() )
2875 if( pStyleSheet->IsUserDefined() && !lclIsBuiltInStyle( pStyleSheet->GetName() ) )
2876 InsertStyleXF( *pStyleSheet );
2877 }
2878
AppendBuiltInXF(XclExpXFRef xXF,sal_uInt8 nStyleId,sal_uInt8 nLevel)2879 sal_uInt32 XclExpXFBuffer::AppendBuiltInXF( XclExpXFRef xXF, sal_uInt8 nStyleId, sal_uInt8 nLevel )
2880 {
2881 sal_uInt32 nXFId = static_cast< sal_uInt32 >( maXFList.GetSize() );
2882 maXFList.AppendRecord( xXF );
2883 XclExpBuiltInInfo& rInfo = maBuiltInMap[ nXFId ];
2884 rInfo.mnStyleId = nStyleId;
2885 rInfo.mnLevel = nLevel;
2886 rInfo.mbPredefined = true;
2887 return nXFId;
2888 }
2889
AppendBuiltInXFWithStyle(XclExpXFRef xXF,sal_uInt8 nStyleId,sal_uInt8 nLevel)2890 sal_uInt32 XclExpXFBuffer::AppendBuiltInXFWithStyle( XclExpXFRef xXF, sal_uInt8 nStyleId, sal_uInt8 nLevel )
2891 {
2892 sal_uInt32 nXFId = AppendBuiltInXF( xXF, nStyleId, nLevel );
2893 maStyleList.AppendNewRecord( new XclExpStyle( nXFId, nStyleId, nLevel ) );
2894 maBuiltInMap[ nXFId ].mbHasStyleRec = true; // mark existing STYLE record
2895 return nXFId;
2896 }
2897
lcl_GetPatternFill_None()2898 static XclExpCellArea lcl_GetPatternFill_None()
2899 {
2900 XclExpCellArea aFill;
2901 aFill.mnPattern = EXC_PATT_NONE;
2902 return aFill;
2903 }
2904
lcl_GetPatternFill_Gray125()2905 static XclExpCellArea lcl_GetPatternFill_Gray125()
2906 {
2907 XclExpCellArea aFill;
2908 aFill.mnPattern = EXC_PATT_12_5_PERC;
2909 aFill.mnForeColor = 0;
2910 aFill.mnBackColor = 0;
2911 return aFill;
2912 }
2913
InsertDefaultRecords()2914 void XclExpXFBuffer::InsertDefaultRecords()
2915 {
2916 maFills.push_back( lcl_GetPatternFill_None() );
2917 maFills.push_back( lcl_GetPatternFill_Gray125() );
2918
2919 // index 0: default style
2920 if( SfxStyleSheetBase* pDefStyleSheet = GetStyleSheetPool().Find( ScGlobal::GetRscString( STR_STYLENAME_STANDARD ), SFX_STYLE_FAMILY_PARA ) )
2921 {
2922 XclExpXFRef xDefStyle( new XclExpXF( GetRoot(), *pDefStyleSheet ) );
2923 sal_uInt32 nXFId = AppendBuiltInXFWithStyle( xDefStyle, EXC_STYLE_NORMAL );
2924 // mark this XF as not predefined, prevents overwriting
2925 maBuiltInMap[ nXFId ].mbPredefined = false;
2926 }
2927 else
2928 {
2929 DBG_ERRORFILE( "XclExpXFBuffer::InsertDefaultRecords - default style not found" );
2930 XclExpXFRef xDefStyle( new XclExpDefaultXF( GetRoot(), false ) );
2931 xDefStyle->SetAllUsedFlags( true );
2932 AppendBuiltInXFWithStyle( xDefStyle, EXC_STYLE_NORMAL );
2933 }
2934
2935 // index 1-14: RowLevel and ColLevel styles (without STYLE records)
2936 XclExpDefaultXF aLevelStyle( GetRoot(), false );
2937 // RowLevel_1, ColLevel_1
2938 aLevelStyle.SetFont( 1 );
2939 AppendBuiltInXF( XclExpXFRef( new XclExpDefaultXF( aLevelStyle ) ), EXC_STYLE_ROWLEVEL, 0 );
2940 AppendBuiltInXF( XclExpXFRef( new XclExpDefaultXF( aLevelStyle ) ), EXC_STYLE_COLLEVEL, 0 );
2941 // RowLevel_2, ColLevel_2
2942 aLevelStyle.SetFont( 2 );
2943 AppendBuiltInXF( XclExpXFRef( new XclExpDefaultXF( aLevelStyle ) ), EXC_STYLE_ROWLEVEL, 1 );
2944 AppendBuiltInXF( XclExpXFRef( new XclExpDefaultXF( aLevelStyle ) ), EXC_STYLE_COLLEVEL, 1 );
2945 // RowLevel_3, ColLevel_3 ... RowLevel_7, ColLevel_7
2946 aLevelStyle.SetFont( 0 );
2947 for( sal_uInt8 nLevel = 2; nLevel < EXC_STYLE_LEVELCOUNT; ++nLevel )
2948 {
2949 AppendBuiltInXF( XclExpXFRef( new XclExpDefaultXF( aLevelStyle ) ), EXC_STYLE_ROWLEVEL, nLevel );
2950 AppendBuiltInXF( XclExpXFRef( new XclExpDefaultXF( aLevelStyle ) ), EXC_STYLE_COLLEVEL, nLevel );
2951 }
2952
2953 // index 15: default hard cell format, placeholder to be able to add more built-in styles
2954 maXFList.AppendNewRecord( new XclExpDefaultXF( GetRoot(), true ) );
2955 maBuiltInMap[ EXC_XF_DEFAULTCELL ].mbPredefined = true;
2956
2957 // index 16-20: other built-in styles
2958 XclExpDefaultXF aFormatStyle( GetRoot(), false );
2959 aFormatStyle.SetFont( 1 );
2960 aFormatStyle.SetNumFmt( 43 );
2961 AppendBuiltInXFWithStyle( XclExpXFRef( new XclExpDefaultXF( aFormatStyle ) ), EXC_STYLE_COMMA );
2962 aFormatStyle.SetNumFmt( 41 );
2963 AppendBuiltInXFWithStyle( XclExpXFRef( new XclExpDefaultXF( aFormatStyle ) ), EXC_STYLE_COMMA_0 );
2964 aFormatStyle.SetNumFmt( 44 );
2965 AppendBuiltInXFWithStyle( XclExpXFRef( new XclExpDefaultXF( aFormatStyle ) ), EXC_STYLE_CURRENCY );
2966 aFormatStyle.SetNumFmt( 42 );
2967 AppendBuiltInXFWithStyle( XclExpXFRef( new XclExpDefaultXF( aFormatStyle ) ), EXC_STYLE_CURRENCY_0 );
2968 aFormatStyle.SetNumFmt( 9 );
2969 AppendBuiltInXFWithStyle( XclExpXFRef( new XclExpDefaultXF( aFormatStyle ) ), EXC_STYLE_PERCENT );
2970
2971 // other built-in style XF records (i.e. Hyperlink styles) are created on demand
2972
2973 /* Insert the real default hard cell format -> 0 is document default pattern.
2974 Do it here (and not already above) to really have all built-in styles. */
2975 Insert( 0, GetDefApiScript() );
2976 }
2977
AppendXFIndex(sal_uInt32 nXFId)2978 void XclExpXFBuffer::AppendXFIndex( sal_uInt32 nXFId )
2979 {
2980 DBG_ASSERT( nXFId < maXFIndexVec.size(), "XclExpXFBuffer::AppendXFIndex - XF ID out of range" );
2981 maXFIndexVec[ nXFId ] = static_cast< sal_uInt16 >( maSortedXFList.GetSize() );
2982 XclExpXFRef xXF = maXFList.GetRecord( nXFId );
2983 AddBorderAndFill( *xXF );
2984 maSortedXFList.AppendRecord( xXF );
2985 DBG_ASSERT( maXFList.HasRecord( nXFId ), "XclExpXFBuffer::AppendXFIndex - XF not found" );
2986 }
2987
AddBorderAndFill(const XclExpXF & rXF)2988 void XclExpXFBuffer::AddBorderAndFill( const XclExpXF& rXF )
2989 {
2990 if( std::find_if( maBorders.begin(), maBorders.end(), XclExpBorderPred( rXF.GetBorderData() ) ) == maBorders.end() )
2991 {
2992 maBorders.push_back( rXF.GetBorderData() );
2993 }
2994
2995 if( std::find_if( maFills.begin(), maFills.end(), XclExpFillPred( rXF.GetAreaData() ) ) == maFills.end() )
2996 {
2997 maFills.push_back( rXF.GetAreaData() );
2998 }
2999 }
3000
3001 // ============================================================================
3002
XclExpXmlStyleSheet(const XclExpRoot & rRoot)3003 XclExpXmlStyleSheet::XclExpXmlStyleSheet( const XclExpRoot& rRoot )
3004 : XclExpRoot( rRoot )
3005 {
3006 }
3007
SaveXml(XclExpXmlStream & rStrm)3008 void XclExpXmlStyleSheet::SaveXml( XclExpXmlStream& rStrm )
3009 {
3010 sax_fastparser::FSHelperPtr aStyleSheet = rStrm.CreateOutputStream(
3011 OUString::createFromAscii( "xl/styles.xml" ),
3012 OUString::createFromAscii( "styles.xml" ),
3013 rStrm.GetCurrentStream()->getOutputStream(),
3014 "application/vnd.openxmlformats-officedocument.spreadsheetml.styles+xml",
3015 "http://schemas.openxmlformats.org/officeDocument/2006/relationships/styles" );
3016 rStrm.PushStream( aStyleSheet );
3017
3018 aStyleSheet->startElement( XML_styleSheet,
3019 XML_xmlns, "http://schemas.openxmlformats.org/spreadsheetml/2006/main",
3020 FSEND );
3021
3022 CreateRecord( EXC_ID_FORMATLIST )->SaveXml( rStrm );
3023 CreateRecord( EXC_ID_FONTLIST )->SaveXml( rStrm );
3024 CreateRecord( EXC_ID_XFLIST )->SaveXml( rStrm );
3025 CreateRecord( EXC_ID_PALETTE )->SaveXml( rStrm );
3026
3027 aStyleSheet->endElement( XML_styleSheet );
3028
3029 rStrm.PopStream();
3030 }
3031
3032 // ============================================================================
3033
3034