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