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