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