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