1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
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/.
9 * This file incorporates work covered by the following license notice:
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 .
21 #include <xestyle.hxx>
25 #include <com/sun/star/i18n/ScriptType.hpp>
26 #include <comphelper/processfactory.hxx>
27 #include <rtl/tencinfo.h>
28 #include <vcl/font.hxx>
29 #include <svl/languageoptions.hxx>
30 #include <scitems.hxx>
31 #include <editeng/borderline.hxx>
32 #include <editeng/boxitem.hxx>
33 #include <editeng/lineitem.hxx>
34 #include <editeng/brushitem.hxx>
35 #include <editeng/frmdiritem.hxx>
36 #include <editeng/fontitem.hxx>
37 #include <editeng/justifyitem.hxx>
38 #include <editeng/langitem.hxx>
39 #include <document.hxx>
40 #include <stlpool.hxx>
41 #include <stlsheet.hxx>
42 #include <patattr.hxx>
44 #include <globstr.hrc>
45 #include <scresid.hxx>
46 #include <xestring.hxx>
47 #include <xltools.hxx>
48 #include <conditio.hxx>
50 #include <filterentries.hxx>
52 #include <o3tl/safeint.hxx>
53 #include <oox/export/utils.hxx>
54 #include <oox/token/tokens.hxx>
55 #include <oox/token/namespaces.hxx>
56 #include <oox/token/relationship.hxx>
57 #include <svl/numformat.hxx>
59 using namespace ::com::sun::star
;
62 // PALETTE record - color information =========================================
66 sal_uInt32
lclGetWeighting( XclExpColorType eType
)
70 case EXC_COLOR_CHARTLINE
: return 1;
71 case EXC_COLOR_CELLBORDER
:
72 case EXC_COLOR_CHARTAREA
: return 2;
73 case EXC_COLOR_CELLTEXT
:
74 case EXC_COLOR_CHARTTEXT
:
75 case EXC_COLOR_CTRLTEXT
: return 10;
77 case EXC_COLOR_CELLAREA
: return 20;
78 case EXC_COLOR_GRID
: return 50;
79 default: OSL_FAIL( "lclGetWeighting - unknown color type" );
84 sal_Int32
lclGetColorDistance( const Color
& rColor1
, const Color
& rColor2
)
86 sal_Int32 nDist
= rColor1
.GetRed() - rColor2
.GetRed();
88 sal_Int32 nDummy
= rColor1
.GetGreen() - rColor2
.GetGreen();
89 nDist
+= nDummy
* nDummy
* 151;
90 nDummy
= rColor1
.GetBlue() - rColor2
.GetBlue();
91 nDist
+= nDummy
* nDummy
* 28;
95 sal_uInt8
lclGetMergedColorComp( sal_uInt8 nComp1
, sal_uInt32 nWeight1
, sal_uInt8 nComp2
, sal_uInt32 nWeight2
)
97 sal_uInt8 nComp1Dist
= ::std::min
< sal_uInt8
>( nComp1
, 0xFF - nComp1
);
98 sal_uInt8 nComp2Dist
= ::std::min
< sal_uInt8
>( nComp2
, 0xFF - nComp2
);
99 if( nComp1Dist
!= nComp2Dist
)
101 /* #i36945# One of the passed RGB components is nearer at the limits (0x00 or 0xFF).
102 Increase its weighting to prevent fading of the colors during reduction. */
103 const sal_uInt8
& rnCompNearer
= (nComp1Dist
< nComp2Dist
) ? nComp1
: nComp2
;
104 sal_uInt32
& rnWeight
= (nComp1Dist
< nComp2Dist
) ? nWeight1
: nWeight2
;
105 rnWeight
*= ((rnCompNearer
- 0x80L
) * (rnCompNearer
- 0x7FL
) / 0x1000L
+ 1);
107 sal_uInt32 nWSum
= nWeight1
+ nWeight2
;
108 return static_cast< sal_uInt8
>( (nComp1
* nWeight1
+ nComp2
* nWeight2
+ nWSum
/ 2) / nWSum
);
111 void lclSetMixedColor( Color
& rDest
, const Color
& rSrc1
, const Color
& rSrc2
)
113 rDest
.SetRed( static_cast< sal_uInt8
>( (static_cast< sal_uInt16
>( rSrc1
.GetRed() ) + rSrc2
.GetRed()) / 2 ) );
114 rDest
.SetGreen( static_cast< sal_uInt8
>( (static_cast< sal_uInt16
>( rSrc1
.GetGreen() ) + rSrc2
.GetGreen()) / 2 ) );
115 rDest
.SetBlue( static_cast< sal_uInt8
>( (static_cast< sal_uInt16
>( rSrc1
.GetBlue() ) + rSrc2
.GetBlue()) / 2 ) );
120 // additional classes for color reduction -------------------------------------
124 /** Represents an entry in a color list.
126 The color stores a weighting value, which increases the more the color is
127 used in the document. Heavy-weighted colors will change less than others on
133 Color maColor
; /// The color value of this palette entry.
134 sal_uInt32 mnColorId
; /// Unique color ID for color reduction.
135 sal_uInt32 mnWeight
; /// Weighting for color reduction.
136 bool mbBaseColor
; /// true = Handle as base color, (don't remove/merge).
139 explicit XclListColor( const Color
& rColor
, sal_uInt32 nColorId
);
141 /** Returns the RGB color value of the color. */
142 const Color
& GetColor() const { return maColor
; }
143 /** Returns the unique ID of the color. */
144 sal_uInt32
GetColorId() const { return mnColorId
; }
145 /** Returns the current weighting of the color. */
146 sal_uInt32
GetWeighting() const { return mnWeight
; }
147 /** Returns true, if this color is a base color, i.e. it will not be removed or merged. */
148 bool IsBaseColor() const { return mbBaseColor
; }
150 /** Adds the passed weighting to this color. */
151 void AddWeighting( sal_uInt32 nWeight
) { mnWeight
+= nWeight
; }
152 /** Merges this color with rColor, regarding weighting settings. */
153 void Merge( const XclListColor
& rColor
);
156 XclListColor::XclListColor( const Color
& rColor
, sal_uInt32 nColorId
) :
158 mnColorId( nColorId
),
162 ((rColor
.GetRed() == 0x00) || (rColor
.GetRed() == 0xFF)) &&
163 ((rColor
.GetGreen() == 0x00) || (rColor
.GetGreen() == 0xFF)) &&
164 ((rColor
.GetBlue() == 0x00) || (rColor
.GetBlue() == 0xFF));
167 void XclListColor::Merge( const XclListColor
& rColor
)
169 sal_uInt32 nWeight2
= rColor
.GetWeighting();
170 // do not change RGB value of base colors
173 maColor
.SetRed( lclGetMergedColorComp( maColor
.GetRed(), mnWeight
, rColor
.maColor
.GetRed(), nWeight2
) );
174 maColor
.SetGreen( lclGetMergedColorComp( maColor
.GetGreen(), mnWeight
, rColor
.maColor
.GetGreen(), nWeight2
) );
175 maColor
.SetBlue( lclGetMergedColorComp( maColor
.GetBlue(), mnWeight
, rColor
.maColor
.GetBlue(), nWeight2
) );
177 AddWeighting( nWeight2
);
180 /** Data for each inserted original color, represented by a color ID. */
181 struct XclColorIdData
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 void Set( const Color
& rColor
, sal_uInt32 nIndex
) { maColor
= rColor
; mnIndex
= nIndex
; }
189 /** A color that will be written to the Excel file. */
190 struct XclPaletteColor
192 Color maColor
; /// Resulting color to export.
193 bool mbUsed
; /// true = Entry is used in the document.
195 explicit XclPaletteColor( const Color
& rColor
) : maColor( rColor
), mbUsed( false ) {}
196 void SetColor( const Color
& rColor
) { maColor
= rColor
; mbUsed
= true; }
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. */
203 sal_uInt32 mnPalIndex
; /// Index to palette.
204 bool mbProcessed
; /// true = List color already processed.
206 explicit XclRemap() : mnPalIndex( 0 ), mbProcessed( false ) {}
207 void SetIndex( sal_uInt32 nPalIndex
)
208 { mnPalIndex
= nPalIndex
; mbProcessed
= true; }
211 /** Stores the nearest palette color index of a list color. */
214 sal_uInt32 mnPalIndex
; /// Index to nearest palette color.
215 sal_Int32 mnDist
; /// Distance to palette color.
217 explicit XclNearest() : mnPalIndex( 0 ), mnDist( 0 ) {}
222 class XclExpPaletteImpl
225 explicit XclExpPaletteImpl( const XclDefaultPalette
& rDefPal
);
227 /** Inserts the color into the list and updates weighting.
228 @param nAutoDefault The Excel palette index for automatic color.
229 @return A unique ID for this color. */
230 sal_uInt32
InsertColor( const Color
& rColor
, XclExpColorType eType
, sal_uInt16 nAutoDefault
= 0 );
231 /** Returns the color ID representing a fixed Excel palette index (i.e. for auto colors). */
232 static sal_uInt32
GetColorIdFromIndex( sal_uInt16 nIndex
);
234 /** Reduces the color list to the maximum count of the current BIFF version. */
237 /** Returns the Excel palette index of the color with passed color ID. */
238 sal_uInt16
GetColorIndex( sal_uInt32 nColorId
) const;
240 /** Returns a foreground and background color for the two passed color IDs.
241 @descr If rnXclPattern contains a solid pattern, this function tries to find
242 the two best fitting colors and a mix pattern (25%, 50% or 75%) for nForeColorId.
243 This will result in a better approximation to the passed foreground color. */
245 sal_uInt16
& rnXclForeIx
, sal_uInt16
& rnXclBackIx
, sal_uInt8
& rnXclPattern
,
246 sal_uInt32 nForeColorId
, sal_uInt32 nBackColorId
) const;
248 /** Returns the RGB color for a (non-zero-based) Excel palette entry.
249 @return The color from current or default palette or COL_AUTO, if nothing else found. */
250 Color
GetColor( sal_uInt16 nXclIndex
) const;
252 /** Returns true, if all colors of the palette are equal to default palette colors. */
253 bool IsDefaultPalette() const;
254 /** Writes the color list (contents of the palette record) to the passed stream. */
255 void WriteBody( XclExpStream
& rStrm
);
256 void SaveXml( XclExpXmlStream
& rStrm
);
259 /** Returns the Excel index of a 0-based color index. */
260 static sal_uInt16
GetXclIndex( sal_uInt32 nIndex
)
261 { return static_cast< sal_uInt16
>( nIndex
+ EXC_COLOR_USEROFFSET
); }
263 /** Returns the original inserted color represented by the color ID nColorId. */
264 const Color
& GetOriginalColor( sal_uInt32 nColorId
) const;
266 /** Searches for rColor, returns the ordered insertion index for rColor in rnIndex. */
267 XclListColor
* SearchListEntry( const Color
& rColor
, sal_uInt32
& rnIndex
);
268 /** Creates and inserts a new color list entry at the specified list position. */
269 XclListColor
* CreateListEntry( const Color
& rColor
, sal_uInt32 nIndex
);
271 /** Raw and fast reduction of the palette. */
272 void RawReducePalette( sal_uInt32 nPass
);
273 /** Reduction of one color using advanced color merging based on color weighting. */
274 void ReduceLeastUsedColor();
276 /** Finds the least used color and returns its current list index. */
277 sal_uInt32
GetLeastUsedListColor() const;
278 /** Returns the list index of the color nearest to rColor.
279 @param nIgnore List index of a color which will be ignored.
280 @return The list index of the found color. */
281 sal_uInt32
GetNearestListColor( const Color
& rColor
, sal_uInt32 nIgnore
) const;
282 /** Returns the list index of the color nearest to the color with list index nIndex. */
283 sal_uInt32
GetNearestListColor( sal_uInt32 nIndex
) const;
285 /** Returns in rnIndex the palette index of the color nearest to rColor.
286 Searches for default colors only (colors never replaced).
287 @return The distance from passed color to found color. */
288 sal_Int32
GetNearestPaletteColor(
290 const Color
& rColor
) const;
291 /** Returns in rnFirst and rnSecond the palette indexes of the two colors nearest to rColor.
292 @return The minimum distance from passed color to found colors. */
293 sal_Int32
GetNearPaletteColors(
294 sal_uInt32
& rnFirst
, sal_uInt32
& rnSecond
,
295 const Color
& rColor
) const;
298 typedef std::vector
< std::unique_ptr
<XclListColor
> > XclListColorList
;
299 typedef std::shared_ptr
< XclListColorList
> XclListColorListRef
;
301 const XclDefaultPalette
& mrDefPal
; /// The default palette for the current BIFF version.
302 XclListColorListRef mxColorList
; /// Working color list.
303 std::vector
< XclColorIdData
>
304 maColorIdDataVec
; /// Data of all CIDs.
305 std::vector
< XclPaletteColor
>
306 maPalette
; /// Contains resulting colors to export.
307 sal_uInt32 mnLastIdx
; /// Last insertion index for search opt.
310 const sal_uInt32 EXC_PAL_INDEXBASE
= 0xFFFF0000;
311 const sal_uInt32 EXC_PAL_MAXRAWSIZE
= 1024;
313 XclExpPaletteImpl::XclExpPaletteImpl( const XclDefaultPalette
& rDefPal
) :
315 mxColorList( std::make_shared
<XclListColorList
>() ),
318 // initialize maPalette with default colors
319 sal_uInt16 nCount
= static_cast< sal_uInt16
>( mrDefPal
.GetColorCount() );
320 maPalette
.reserve( nCount
);
321 for( sal_uInt16 nIdx
= 0; nIdx
< nCount
; ++nIdx
)
322 maPalette
.emplace_back( mrDefPal
.GetDefColor( GetXclIndex( nIdx
) ) );
324 InsertColor( COL_BLACK
, EXC_COLOR_CELLTEXT
);
327 sal_uInt32
XclExpPaletteImpl::InsertColor( const Color
& rColor
, XclExpColorType eType
, sal_uInt16 nAutoDefault
)
329 if( rColor
== COL_AUTO
)
330 return GetColorIdFromIndex( nAutoDefault
);
332 sal_uInt32 nFoundIdx
= 0;
333 XclListColor
* pEntry
= SearchListEntry( rColor
, nFoundIdx
);
334 if( !pEntry
|| (pEntry
->GetColor() != rColor
) )
335 pEntry
= CreateListEntry( rColor
, nFoundIdx
);
336 pEntry
->AddWeighting( lclGetWeighting( eType
) );
338 return pEntry
->GetColorId();
341 sal_uInt32
XclExpPaletteImpl::GetColorIdFromIndex( sal_uInt16 nIndex
)
343 return EXC_PAL_INDEXBASE
| nIndex
;
346 void XclExpPaletteImpl::Finalize()
348 // --- build initial color ID data vector (maColorIdDataVec) ---
350 sal_uInt32 nCount
= mxColorList
->size();
351 maColorIdDataVec
.resize( nCount
);
352 for( sal_uInt32 nIdx
= 0; nIdx
< nCount
; ++nIdx
)
354 const XclListColor
& listColor
= *mxColorList
->at( nIdx
);
355 maColorIdDataVec
[ listColor
.GetColorId() ].Set( listColor
.GetColor(), nIdx
);
358 // --- loop as long as current color count does not fit into palette of current BIFF ---
360 // phase 1: raw reduction (performance reasons, #i36945#)
361 sal_uInt32 nPass
= 0;
362 while( mxColorList
->size() > EXC_PAL_MAXRAWSIZE
)
363 RawReducePalette( nPass
++ );
365 // phase 2: precise reduction using advanced color merging based on color weighting
366 while( mxColorList
->size() > mrDefPal
.GetColorCount() )
367 ReduceLeastUsedColor();
369 // --- use default palette and replace colors with nearest used colors ---
371 nCount
= mxColorList
->size();
372 std::vector
< XclRemap
> aRemapVec( nCount
);
373 std::vector
< XclNearest
> aNearestVec( nCount
);
375 // in each run: search the best fitting color and replace a default color with it
376 for( sal_uInt32 nRun
= 0; nRun
< nCount
; ++nRun
)
379 // find nearest unused default color for each unprocessed list color
380 for( nIndex
= 0; nIndex
< nCount
; ++nIndex
)
381 aNearestVec
[ nIndex
].mnDist
= aRemapVec
[ nIndex
].mbProcessed
? SAL_MAX_INT32
:
382 GetNearestPaletteColor( aNearestVec
[ nIndex
].mnPalIndex
, mxColorList
->at( nIndex
)->GetColor() );
383 // find the list color which is nearest to a default color
384 sal_uInt32 nFound
= 0;
385 for( nIndex
= 1; nIndex
< nCount
; ++nIndex
)
386 if( aNearestVec
[ nIndex
].mnDist
< aNearestVec
[ nFound
].mnDist
)
388 // replace default color with list color
389 sal_uInt32 nNearest
= aNearestVec
[ nFound
].mnPalIndex
;
390 OSL_ENSURE( nNearest
< maPalette
.size(), "XclExpPaletteImpl::Finalize - algorithm error" );
391 maPalette
[ nNearest
].SetColor( mxColorList
->at( nFound
)->GetColor() );
392 aRemapVec
[ nFound
].SetIndex( nNearest
);
395 // remap color ID data map (maColorIdDataVec) from list indexes to palette indexes
396 for( auto& rColorIdData
: maColorIdDataVec
)
397 rColorIdData
.mnIndex
= aRemapVec
[ rColorIdData
.mnIndex
].mnPalIndex
;
400 sal_uInt16
XclExpPaletteImpl::GetColorIndex( sal_uInt32 nColorId
) const
403 if( nColorId
>= EXC_PAL_INDEXBASE
)
404 nRet
= static_cast< sal_uInt16
>( nColorId
& ~EXC_PAL_INDEXBASE
);
405 else if( nColorId
< maColorIdDataVec
.size() )
406 nRet
= GetXclIndex( maColorIdDataVec
[ nColorId
].mnIndex
);
410 void XclExpPaletteImpl::GetMixedColors(
411 sal_uInt16
& rnXclForeIx
, sal_uInt16
& rnXclBackIx
, sal_uInt8
& rnXclPattern
,
412 sal_uInt32 nForeColorId
, sal_uInt32 nBackColorId
) const
414 rnXclForeIx
= GetColorIndex( nForeColorId
);
415 rnXclBackIx
= GetColorIndex( nBackColorId
);
416 if( (rnXclPattern
!= EXC_PATT_SOLID
) || (nForeColorId
>= maColorIdDataVec
.size()) )
419 // now we have solid pattern, and a defined foreground (background doesn't care for solid pattern)
421 sal_uInt32 nIndex1
, nIndex2
;
422 Color
aForeColor( GetOriginalColor( nForeColorId
) );
423 sal_Int32 nFirstDist
= GetNearPaletteColors( nIndex1
, nIndex2
, aForeColor
);
424 if( (nIndex1
>= maPalette
.size()) || (nIndex2
>= maPalette
.size()) )
427 Color aColorArr
[ 5 ];
428 aColorArr
[ 0 ] = maPalette
[ nIndex1
].maColor
;
429 aColorArr
[ 4 ] = maPalette
[ nIndex2
].maColor
;
430 lclSetMixedColor( aColorArr
[ 2 ], aColorArr
[ 0 ], aColorArr
[ 4 ] );
431 lclSetMixedColor( aColorArr
[ 1 ], aColorArr
[ 0 ], aColorArr
[ 2 ] );
432 lclSetMixedColor( aColorArr
[ 3 ], aColorArr
[ 2 ], aColorArr
[ 4 ] );
434 sal_Int32 nMinDist
= nFirstDist
;
435 sal_uInt32 nMinIndex
= 0;
436 for( sal_uInt32 nCnt
= 1; nCnt
< 4; ++nCnt
)
438 sal_Int32 nDist
= lclGetColorDistance( aForeColor
, aColorArr
[ nCnt
] );
439 if( nDist
< nMinDist
)
445 rnXclForeIx
= GetXclIndex( nIndex1
);
446 rnXclBackIx
= GetXclIndex( nIndex2
);
447 if( nMinDist
< nFirstDist
)
451 case 1: rnXclPattern
= EXC_PATT_75_PERC
; break;
452 case 2: rnXclPattern
= EXC_PATT_50_PERC
; break;
453 case 3: rnXclPattern
= EXC_PATT_25_PERC
; break;
458 Color
XclExpPaletteImpl::GetColor( sal_uInt16 nXclIndex
) const
460 if( nXclIndex
>= EXC_COLOR_USEROFFSET
)
462 sal_uInt32 nIdx
= nXclIndex
- EXC_COLOR_USEROFFSET
;
463 if( nIdx
< maPalette
.size() )
464 return maPalette
[ nIdx
].maColor
;
466 return mrDefPal
.GetDefColor( nXclIndex
);
469 bool XclExpPaletteImpl::IsDefaultPalette() const
471 bool bDefault
= true;
472 for( sal_uInt32 nIdx
= 0, nSize
= static_cast< sal_uInt32
>( maPalette
.size() ); bDefault
&& (nIdx
< nSize
); ++nIdx
)
473 bDefault
= maPalette
[ nIdx
].maColor
== mrDefPal
.GetDefColor( GetXclIndex( nIdx
) );
477 void XclExpPaletteImpl::WriteBody( XclExpStream
& rStrm
)
479 rStrm
<< static_cast< sal_uInt16
>( maPalette
.size() );
480 for( const auto& rColor
: maPalette
)
481 rStrm
<< rColor
.maColor
;
484 void XclExpPaletteImpl::SaveXml( XclExpXmlStream
& rStrm
)
486 if( maPalette
.empty() )
489 sax_fastparser::FSHelperPtr
& rStyleSheet
= rStrm
.GetCurrentStream();
490 rStyleSheet
->startElement(XML_colors
);
491 rStyleSheet
->startElement(XML_indexedColors
);
492 for( const auto& rColor
: maPalette
)
493 rStyleSheet
->singleElement(XML_rgbColor
, XML_rgb
, XclXmlUtils::ToOString(rColor
.maColor
));
494 rStyleSheet
->endElement( XML_indexedColors
);
495 rStyleSheet
->endElement( XML_colors
);
498 const Color
& XclExpPaletteImpl::GetOriginalColor( sal_uInt32 nColorId
) const
500 if( nColorId
< maColorIdDataVec
.size() )
501 return maColorIdDataVec
[ nColorId
].maColor
;
502 return maPalette
[ 0 ].maColor
;
505 XclListColor
* XclExpPaletteImpl::SearchListEntry( const Color
& rColor
, sal_uInt32
& rnIndex
)
509 if (mxColorList
->empty())
512 XclListColor
* pEntry
= nullptr;
514 // search optimization for equal-colored objects occurring repeatedly
515 if (mnLastIdx
< mxColorList
->size())
517 pEntry
= (*mxColorList
)[mnLastIdx
].get();
518 if( pEntry
->GetColor() == rColor
)
525 // binary search for color
526 sal_uInt32 nBegIdx
= 0;
527 sal_uInt32 nEndIdx
= mxColorList
->size();
529 while( !bFound
&& (nBegIdx
< nEndIdx
) )
531 rnIndex
= (nBegIdx
+ nEndIdx
) / 2;
532 pEntry
= (*mxColorList
)[rnIndex
].get();
533 bFound
= pEntry
->GetColor() == rColor
;
536 if( pEntry
->GetColor() < rColor
)
537 nBegIdx
= rnIndex
+ 1;
543 // not found - use end of range as new insertion position
551 XclListColor
* XclExpPaletteImpl::CreateListEntry( const Color
& rColor
, sal_uInt32 nIndex
)
553 XclListColor
* pEntry
= new XclListColor( rColor
, mxColorList
->size() );
554 mxColorList
->insert(mxColorList
->begin() + nIndex
, std::unique_ptr
<XclListColor
>(pEntry
));
558 void XclExpPaletteImpl::RawReducePalette( sal_uInt32 nPass
)
560 /* Fast palette reduction - in each call of this function one RGB component
561 of each color is reduced to a lower number of distinct values.
562 Pass 0: Blue is reduced to 128 distinct values.
563 Pass 1: Red is reduced to 128 distinct values.
564 Pass 2: Green is reduced to 128 distinct values.
565 Pass 3: Blue is reduced to 64 distinct values.
566 Pass 4: Red is reduced to 64 distinct values.
567 Pass 5: Green is reduced to 64 distinct values.
571 XclListColorListRef xOldList
= mxColorList
;
572 mxColorList
= std::make_shared
<XclListColorList
>();
574 // maps old list indexes to new list indexes, used to update maColorIdDataVec
575 ScfUInt32Vec aListIndexMap
;
576 aListIndexMap
.reserve( xOldList
->size() );
579 sal_uInt8 nR
, nG
, nB
;
580 sal_uInt8
& rnComp
= ((nPass
% 3 == 0) ? nB
: ((nPass
% 3 == 1) ? nR
: nG
));
582 OSL_ENSURE( nPass
< 7, "XclExpPaletteImpl::RawReducePalette - reduction not terminated" );
584 static const sal_uInt8 spnFactor2
[] = { 0x81, 0x82, 0x84, 0x88, 0x92, 0xAA, 0xFF };
585 sal_uInt8 nFactor1
= static_cast< sal_uInt8
>( 0x02 << nPass
);
586 sal_uInt8 nFactor2
= spnFactor2
[ nPass
];
587 sal_uInt8 nFactor3
= static_cast< sal_uInt8
>( 0x40 >> nPass
);
589 // process each color in the old color list
590 for(const std::unique_ptr
<XclListColor
> & pOldColor
: *xOldList
)
592 // get the old list entry
593 const XclListColor
* pOldEntry
= pOldColor
.get();
594 nR
= pOldEntry
->GetColor().GetRed();
595 nG
= pOldEntry
->GetColor().GetGreen();
596 nB
= pOldEntry
->GetColor().GetBlue();
598 /* Calculate the new RGB component (rnComp points to one of nR, nG, nB).
599 Using integer arithmetic with its rounding errors, the results of
600 this calculation are always exactly in the range 0x00 to 0xFF
601 (simply cutting the lower bits would darken the colors slightly). */
602 sal_uInt32 nNewComp
= rnComp
;
603 nNewComp
/= nFactor1
;
604 nNewComp
*= nFactor2
;
605 nNewComp
/= nFactor3
;
606 rnComp
= static_cast< sal_uInt8
>( nNewComp
);
607 Color
aNewColor( nR
, nG
, nB
);
609 // find or insert the new color
610 sal_uInt32 nFoundIdx
= 0;
611 XclListColor
* pNewEntry
= SearchListEntry( aNewColor
, nFoundIdx
);
612 if( !pNewEntry
|| (pNewEntry
->GetColor() != aNewColor
) )
613 pNewEntry
= CreateListEntry( aNewColor
, nFoundIdx
);
614 pNewEntry
->AddWeighting( pOldEntry
->GetWeighting() );
615 aListIndexMap
.push_back( nFoundIdx
);
618 // update color ID data map (maps color IDs to color list indexes), replace old by new list indexes
619 for( auto& rColorIdData
: maColorIdDataVec
)
620 rColorIdData
.mnIndex
= aListIndexMap
[ rColorIdData
.mnIndex
];
623 void XclExpPaletteImpl::ReduceLeastUsedColor()
625 // find a list color to remove
626 sal_uInt32 nRemove
= GetLeastUsedListColor();
627 // find its nearest neighbor
628 sal_uInt32 nKeep
= GetNearestListColor( nRemove
);
630 // merge both colors to one color, remove one color from list
631 XclListColor
* pKeepEntry
= mxColorList
->at(nKeep
).get();
632 XclListColor
* pRemoveEntry
= mxColorList
->at(nRemove
).get();
633 if( !(pKeepEntry
&& pRemoveEntry
) )
636 // merge both colors (if pKeepEntry is a base color, it will not change)
637 pKeepEntry
->Merge( *pRemoveEntry
);
638 // remove the less used color, adjust nKeep index if kept color follows removed color
639 XclListColorList::iterator itr
= mxColorList
->begin();
640 ::std::advance(itr
, nRemove
);
641 mxColorList
->erase(itr
);
642 if( nKeep
> nRemove
) --nKeep
;
644 // recalculate color ID data map (maps color IDs to color list indexes)
645 for( auto& rColorIdData
: maColorIdDataVec
)
647 if( rColorIdData
.mnIndex
> nRemove
)
648 --rColorIdData
.mnIndex
;
649 else if( rColorIdData
.mnIndex
== nRemove
)
650 rColorIdData
.mnIndex
= nKeep
;
654 sal_uInt32
XclExpPaletteImpl::GetLeastUsedListColor() const
656 sal_uInt32 nFound
= 0;
657 sal_uInt32 nMinW
= SAL_MAX_UINT32
;
659 for( sal_uInt32 nIdx
= 0, nCount
= mxColorList
->size(); nIdx
< nCount
; ++nIdx
)
661 XclListColor
& rEntry
= *mxColorList
->at( nIdx
);
662 // ignore the base colors
663 if( !rEntry
.IsBaseColor() && (rEntry
.GetWeighting() < nMinW
) )
666 nMinW
= rEntry
.GetWeighting();
672 sal_uInt32
XclExpPaletteImpl::GetNearestListColor( const Color
& rColor
, sal_uInt32 nIgnore
) const
674 sal_uInt32 nFound
= 0;
675 sal_Int32 nMinD
= SAL_MAX_INT32
;
677 for( sal_uInt32 nIdx
= 0, nCount
= mxColorList
->size(); nIdx
< nCount
; ++nIdx
)
679 if( nIdx
!= nIgnore
)
681 if( XclListColor
* pEntry
= mxColorList
->at(nIdx
).get() )
683 sal_Int32 nDist
= lclGetColorDistance( rColor
, pEntry
->GetColor() );
695 sal_uInt32
XclExpPaletteImpl::GetNearestListColor( sal_uInt32 nIndex
) const
697 if (nIndex
>= mxColorList
->size())
699 XclListColor
* pEntry
= mxColorList
->at(nIndex
).get();
700 return GetNearestListColor( pEntry
->GetColor(), nIndex
);
703 sal_Int32
XclExpPaletteImpl::GetNearestPaletteColor(
704 sal_uInt32
& rnIndex
, const Color
& rColor
) const
707 sal_Int32 nDist
= SAL_MAX_INT32
;
709 sal_uInt32 nPaletteIndex
= 0;
710 for( const auto& rPaletteColor
: maPalette
)
712 if( !rPaletteColor
.mbUsed
)
714 sal_Int32 nCurrDist
= lclGetColorDistance( rColor
, rPaletteColor
.maColor
);
715 if( nCurrDist
< nDist
)
717 rnIndex
= nPaletteIndex
;
726 sal_Int32
XclExpPaletteImpl::GetNearPaletteColors(
727 sal_uInt32
& rnFirst
, sal_uInt32
& rnSecond
, const Color
& rColor
) const
729 rnFirst
= rnSecond
= 0;
730 sal_Int32 nDist1
= SAL_MAX_INT32
;
731 sal_Int32 nDist2
= SAL_MAX_INT32
;
733 sal_uInt32 nPaletteIndex
= 0;
734 for( const auto& rPaletteColor
: maPalette
)
736 sal_Int32 nCurrDist
= lclGetColorDistance( rColor
, rPaletteColor
.maColor
);
737 if( nCurrDist
< nDist1
)
741 rnFirst
= nPaletteIndex
;
744 else if( nCurrDist
< nDist2
)
746 rnSecond
= nPaletteIndex
;
754 XclExpPalette::XclExpPalette( const XclExpRoot
& rRoot
) :
755 XclDefaultPalette( rRoot
),
756 XclExpRecord( EXC_ID_PALETTE
)
758 mxImpl
= std::make_shared
<XclExpPaletteImpl
>( *this );
759 SetRecSize( GetColorCount() * 4 + 2 );
762 XclExpPalette::~XclExpPalette()
766 sal_uInt32
XclExpPalette::InsertColor( const Color
& rColor
, XclExpColorType eType
, sal_uInt16 nAutoDefault
)
768 return mxImpl
->InsertColor( rColor
, eType
, nAutoDefault
);
771 sal_uInt32
XclExpPalette::GetColorIdFromIndex( sal_uInt16 nIndex
)
773 return XclExpPaletteImpl::GetColorIdFromIndex( nIndex
);
776 void XclExpPalette::Finalize()
781 sal_uInt16
XclExpPalette::GetColorIndex( sal_uInt32 nColorId
) const
783 return mxImpl
->GetColorIndex( nColorId
);
786 void XclExpPalette::GetMixedColors(
787 sal_uInt16
& rnXclForeIx
, sal_uInt16
& rnXclBackIx
, sal_uInt8
& rnXclPattern
,
788 sal_uInt32 nForeColorId
, sal_uInt32 nBackColorId
) const
790 return mxImpl
->GetMixedColors( rnXclForeIx
, rnXclBackIx
, rnXclPattern
, nForeColorId
, nBackColorId
);
793 Color
XclExpPalette::GetColor( sal_uInt16 nXclIndex
) const
795 return mxImpl
->GetColor( nXclIndex
);
798 void XclExpPalette::Save( XclExpStream
& rStrm
)
800 if( !mxImpl
->IsDefaultPalette() )
801 XclExpRecord::Save( rStrm
);
804 void XclExpPalette::SaveXml( XclExpXmlStream
& rStrm
)
806 if( !mxImpl
->IsDefaultPalette() )
807 mxImpl
->SaveXml( rStrm
);
810 void XclExpPalette::WriteBody( XclExpStream
& rStrm
)
812 mxImpl
->WriteBody( rStrm
);
815 // FONT record - font information =============================================
819 typedef ::std::pair
< sal_uInt16
, sal_Int16
> WhichAndScript
;
821 sal_Int16
lclCheckFontItems( const SfxItemSet
& rItemSet
,
822 const WhichAndScript
& rWAS1
, const WhichAndScript
& rWAS2
, const WhichAndScript
& rWAS3
)
824 if( ScfTools::CheckItem( rItemSet
, rWAS1
.first
, false ) ) return rWAS1
.second
;
825 if( ScfTools::CheckItem( rItemSet
, rWAS2
.first
, false ) ) return rWAS2
.second
;
826 if( ScfTools::CheckItem( rItemSet
, rWAS3
.first
, false ) ) return rWAS3
.second
;
832 sal_Int16
XclExpFontHelper::GetFirstUsedScript( const XclExpRoot
& rRoot
, const SfxItemSet
& rItemSet
)
834 namespace ApiScriptType
= ::com::sun::star::i18n::ScriptType
;
836 /* #i17050# #i107170# We need to determine which font items are set in the
837 item set, and which script type we should prefer according to the
838 current language settings. */
840 static const WhichAndScript
WAS_LATIN( ATTR_FONT
, css::i18n::ScriptType::LATIN
);
841 static const WhichAndScript
WAS_ASIAN( ATTR_CJK_FONT
, css::i18n::ScriptType::ASIAN
);
842 static const WhichAndScript
WAS_CMPLX( ATTR_CTL_FONT
, css::i18n::ScriptType::COMPLEX
);
844 /* do not let a font from a parent style override an explicit
847 sal_Int16 nDefScript
= rRoot
.GetDefApiScript();
848 sal_Int16 nScript
= 0;
849 const SfxItemSet
* pCurrSet
= &rItemSet
;
851 while( (nScript
== 0) && pCurrSet
)
855 case ApiScriptType::LATIN
:
856 nScript
= lclCheckFontItems( *pCurrSet
, WAS_LATIN
, WAS_CMPLX
, WAS_ASIAN
);
858 case ApiScriptType::ASIAN
:
859 nScript
= lclCheckFontItems( *pCurrSet
, WAS_ASIAN
, WAS_CMPLX
, WAS_LATIN
);
861 case ApiScriptType::COMPLEX
:
862 nScript
= lclCheckFontItems( *pCurrSet
, WAS_CMPLX
, WAS_ASIAN
, WAS_LATIN
);
865 OSL_FAIL( "XclExpFontHelper::GetFirstUsedScript - unknown script type" );
866 nScript
= ApiScriptType::LATIN
;
868 pCurrSet
= pCurrSet
->GetParent();
872 nScript
= nDefScript
;
876 OSL_FAIL( "XclExpFontHelper::GetFirstUsedScript - unknown script type" );
877 nScript
= ApiScriptType::LATIN
;
883 vcl::Font
XclExpFontHelper::GetFontFromItemSet( const XclExpRoot
& rRoot
, const SfxItemSet
& rItemSet
, sal_Int16 nScript
)
885 // if WEAK is passed, guess script type from existing items in the item set
886 if( nScript
== css::i18n::ScriptType::WEAK
)
887 nScript
= GetFirstUsedScript( rRoot
, rItemSet
);
889 // convert to core script type constants
890 SvtScriptType nScScript
= SvtLanguageOptions::FromI18NToSvtScriptType(nScript
);
892 // fill the font object
894 ScPatternAttr::GetFont( aFont
, rItemSet
, SC_AUTOCOL_RAW
, nullptr, nullptr, nullptr, nScScript
);
898 ScDxfFont
XclExpFontHelper::GetDxfFontFromItemSet(const XclExpRoot
& rRoot
, const SfxItemSet
& rItemSet
)
900 sal_Int16 nScript
= GetFirstUsedScript(rRoot
, rItemSet
);
902 // convert to core script type constants
903 SvtScriptType nScScript
= SvtLanguageOptions::FromI18NToSvtScriptType(nScript
);
904 return ScPatternAttr::GetDxfFont(rItemSet
, nScScript
);
907 bool XclExpFontHelper::CheckItems( const XclExpRoot
& rRoot
, const SfxItemSet
& rItemSet
, sal_Int16 nScript
, bool bDeep
)
909 static const sal_uInt16 pnCommonIds
[] = {
910 ATTR_FONT_UNDERLINE
, ATTR_FONT_CROSSEDOUT
, ATTR_FONT_CONTOUR
,
911 ATTR_FONT_SHADOWED
, ATTR_FONT_COLOR
, ATTR_FONT_LANGUAGE
, 0 };
912 static const sal_uInt16 pnLatinIds
[] = {
913 ATTR_FONT
, ATTR_FONT_HEIGHT
, ATTR_FONT_WEIGHT
, ATTR_FONT_POSTURE
, 0 };
914 static const sal_uInt16 pnAsianIds
[] = {
915 ATTR_CJK_FONT
, ATTR_CJK_FONT_HEIGHT
, ATTR_CJK_FONT_WEIGHT
, ATTR_CJK_FONT_POSTURE
, 0 };
916 static const sal_uInt16 pnComplexIds
[] = {
917 ATTR_CTL_FONT
, ATTR_CTL_FONT_HEIGHT
, ATTR_CTL_FONT_WEIGHT
, ATTR_CTL_FONT_POSTURE
, 0 };
919 bool bUsed
= ScfTools::CheckItems( rItemSet
, pnCommonIds
, bDeep
);
922 namespace ApiScriptType
= css::i18n::ScriptType
;
923 // if WEAK is passed, guess script type from existing items in the item set
924 if( nScript
== ApiScriptType::WEAK
)
925 nScript
= GetFirstUsedScript( rRoot
, rItemSet
);
926 // check the correct items
929 case ApiScriptType::LATIN
: bUsed
= ScfTools::CheckItems( rItemSet
, pnLatinIds
, bDeep
); break;
930 case ApiScriptType::ASIAN
: bUsed
= ScfTools::CheckItems( rItemSet
, pnAsianIds
, bDeep
); break;
931 case ApiScriptType::COMPLEX
: bUsed
= ScfTools::CheckItems( rItemSet
, pnComplexIds
, bDeep
); break;
932 default: OSL_FAIL( "XclExpFontHelper::CheckItems - unknown script type" );
940 sal_uInt32
lclCalcHash( const XclFontData
& rFontData
)
942 sal_uInt32 nHash
= rFontData
.maName
.getLength();
943 nHash
+= sal_uInt32(rFontData
.maColor
) * 2;
944 nHash
+= rFontData
.mnWeight
* 3;
945 nHash
+= rFontData
.mnCharSet
* 5;
946 nHash
+= rFontData
.mnFamily
* 7;
947 nHash
+= rFontData
.mnHeight
* 11;
948 nHash
+= rFontData
.mnUnderline
* 13;
949 nHash
+= rFontData
.mnEscapem
* 17;
950 if( rFontData
.mbItalic
) nHash
+= 19;
951 if( rFontData
.mbStrikeout
) nHash
+= 23;
952 if( rFontData
.mbOutline
) nHash
+= 29;
953 if( rFontData
.mbShadow
) nHash
+= 31;
959 XclExpFont::XclExpFont( const XclExpRoot
& rRoot
,
960 const XclFontData
& rFontData
, XclExpColorType eColorType
) :
961 XclExpRecord( EXC_ID2_FONT
, 14 ),
965 // insert font color into palette
966 mnColorId
= rRoot
.GetPalette().InsertColor( rFontData
.maColor
, eColorType
, EXC_COLOR_FONTAUTO
);
967 // hash value for faster comparison
968 mnHash
= lclCalcHash( maData
);
970 sal_Int32 nStrLen
= maData
.maName
.getLength();
971 SetRecSize( ((GetBiff() == EXC_BIFF8
) ? (nStrLen
* 2 + 1) : nStrLen
) + 15 );
974 bool XclExpFont::Equals( const XclFontData
& rFontData
, sal_uInt32 nHash
) const
976 return (mnHash
== nHash
) && (maData
== rFontData
);
979 void XclExpFont::SaveXml( XclExpXmlStream
& rStrm
)
981 sax_fastparser::FSHelperPtr
& rStyleSheet
= rStrm
.GetCurrentStream();
982 rStyleSheet
->startElement(XML_font
);
983 XclXmlUtils::WriteFontData( rStyleSheet
, maData
, XML_name
);
984 // OOXTODO: XML_scheme; //scheme/@val values: "major", "minor", "none"
985 rStyleSheet
->endElement( XML_font
);
988 // private --------------------------------------------------------------------
990 void XclExpFont::WriteBody( XclExpStream
& rStrm
)
992 sal_uInt16 nAttr
= EXC_FONTATTR_NONE
;
993 ::set_flag( nAttr
, EXC_FONTATTR_ITALIC
, maData
.mbItalic
);
994 if( maData
.mnUnderline
> 0 )
995 ::set_flag( nAttr
, EXC_FONTATTR_UNDERLINE
, true );
996 ::set_flag( nAttr
, EXC_FONTATTR_STRIKEOUT
, maData
.mbStrikeout
);
997 ::set_flag( nAttr
, EXC_FONTATTR_OUTLINE
, maData
.mbOutline
);
998 ::set_flag( nAttr
, EXC_FONTATTR_SHADOW
, maData
.mbShadow
);
1000 OSL_ENSURE( maData
.maName
.getLength() < 256, "XclExpFont::WriteBody - font name too long" );
1001 XclExpString aFontName
;
1002 if( GetBiff() <= EXC_BIFF5
)
1003 aFontName
.AssignByte( maData
.maName
, GetTextEncoding(), XclStrFlags::EightBitLength
);
1005 aFontName
.Assign( maData
.maName
, XclStrFlags::ForceUnicode
| XclStrFlags::EightBitLength
);
1007 rStrm
<< maData
.mnHeight
1009 << GetPalette().GetColorIndex( mnColorId
)
1012 << maData
.mnUnderline
1019 XclExpDxfFont::XclExpDxfFont(const XclExpRoot
& rRoot
,
1020 const SfxItemSet
& rItemSet
):
1023 maDxfData
= XclExpFontHelper::GetDxfFontFromItemSet(rRoot
, rItemSet
);
1028 const char* getUnderlineOOXValue(FontLineStyle eUnderline
)
1032 case LINESTYLE_NONE
:
1033 case LINESTYLE_DONTKNOW
:
1035 case LINESTYLE_DOUBLE
:
1036 case LINESTYLE_DOUBLEWAVE
:
1043 const char* getFontFamilyOOXValue(FontFamily eValue
)
1047 case FAMILY_DONTKNOW
:
1058 case FAMILY_DECORATIVE
:
1067 void XclExpDxfFont::SaveXml(XclExpXmlStream
& rStrm
)
1069 if (maDxfData
.isEmpty())
1072 sax_fastparser::FSHelperPtr
& rStyleSheet
= rStrm
.GetCurrentStream();
1073 rStyleSheet
->startElement(XML_font
);
1075 if (maDxfData
.pFontAttr
)
1077 OUString aFontName
= (*maDxfData
.pFontAttr
)->GetFamilyName();
1079 aFontName
= XclTools::GetXclFontName(aFontName
);
1080 if (!aFontName
.isEmpty())
1082 rStyleSheet
->singleElement(XML_name
, XML_val
, aFontName
);
1085 rtl_TextEncoding eTextEnc
= (*maDxfData
.pFontAttr
)->GetCharSet();
1086 sal_uInt8 nExcelCharSet
= rtl_getBestWindowsCharsetFromTextEncoding(eTextEnc
);
1089 rStyleSheet
->singleElement(XML_charset
, XML_val
, OString::number(nExcelCharSet
));
1092 FontFamily eFamily
= (*maDxfData
.pFontAttr
)->GetFamily();
1093 const char* pVal
= getFontFamilyOOXValue(eFamily
);
1096 rStyleSheet
->singleElement(XML_family
, XML_val
, pVal
);
1100 if (maDxfData
.eWeight
)
1102 rStyleSheet
->singleElement(XML_b
,
1103 XML_val
, ToPsz10(*maDxfData
.eWeight
!= WEIGHT_NORMAL
));
1106 if (maDxfData
.eItalic
)
1108 bool bItalic
= (*maDxfData
.eItalic
== ITALIC_OBLIQUE
) || (*maDxfData
.eItalic
== ITALIC_NORMAL
);
1109 rStyleSheet
->singleElement(XML_i
, XML_val
, ToPsz10(bItalic
));
1112 if (maDxfData
.eStrike
)
1115 (*maDxfData
.eStrike
== STRIKEOUT_SINGLE
) || (*maDxfData
.eStrike
== STRIKEOUT_DOUBLE
) ||
1116 (*maDxfData
.eStrike
== STRIKEOUT_BOLD
) || (*maDxfData
.eStrike
== STRIKEOUT_SLASH
) ||
1117 (*maDxfData
.eStrike
== STRIKEOUT_X
);
1119 rStyleSheet
->singleElement(XML_strike
, XML_val
, ToPsz10(bStrikeout
));
1122 if (maDxfData
.bOutline
)
1124 rStyleSheet
->singleElement(XML_outline
, XML_val
, ToPsz10(*maDxfData
.bOutline
));
1127 if (maDxfData
.bShadow
)
1129 rStyleSheet
->singleElement(XML_shadow
, XML_val
, ToPsz10(*maDxfData
.bShadow
));
1132 if (maDxfData
.aColor
)
1134 rStyleSheet
->singleElement(XML_color
,
1135 XML_rgb
, XclXmlUtils::ToOString(*maDxfData
.aColor
));
1138 if (maDxfData
.nFontHeight
)
1140 rStyleSheet
->singleElement(XML_sz
,
1141 XML_val
, OString::number(*maDxfData
.nFontHeight
/20));
1144 if (maDxfData
.eUnder
)
1146 const char* pVal
= getUnderlineOOXValue(*maDxfData
.eUnder
);
1147 rStyleSheet
->singleElement(XML_u
, XML_val
, pVal
);
1150 rStyleSheet
->endElement(XML_font
);
1153 XclExpBlindFont::XclExpBlindFont( const XclExpRoot
& rRoot
) :
1154 XclExpFont( rRoot
, XclFontData(), EXC_COLOR_CELLTEXT
)
1158 bool XclExpBlindFont::Equals( const XclFontData
& /*rFontData*/, sal_uInt32
/*nHash*/ ) const
1163 void XclExpBlindFont::Save( XclExpStream
& /*rStrm*/ )
1168 XclExpFontBuffer::XclExpFontBuffer( const XclExpRoot
& rRoot
) :
1169 XclExpRoot( rRoot
),
1174 case EXC_BIFF4
: mnXclMaxSize
= EXC_FONT_MAXCOUNT4
; break;
1175 case EXC_BIFF5
: mnXclMaxSize
= EXC_FONT_MAXCOUNT5
; break;
1176 case EXC_BIFF8
: mnXclMaxSize
= EXC_FONT_MAXCOUNT8
; break;
1177 default: DBG_ERROR_BIFF();
1182 const XclExpFont
* XclExpFontBuffer::GetFont( sal_uInt16 nXclFont
) const
1184 return maFontList
.GetRecord( nXclFont
);
1187 const XclFontData
& XclExpFontBuffer::GetAppFontData() const
1189 return maFontList
.GetRecord( EXC_FONT_APP
)->GetFontData(); // exists always
1192 sal_uInt16
XclExpFontBuffer::Insert(
1193 const XclFontData
& rFontData
, XclExpColorType eColorType
, bool bAppFont
)
1197 XclExpFontRef xFont
= new XclExpFont( GetRoot(), rFontData
, eColorType
);
1198 maFontList
.ReplaceRecord( xFont
, EXC_FONT_APP
);
1199 // set width of '0' character for column width export
1200 SetCharWidth( xFont
->GetFontData() );
1201 return EXC_FONT_APP
;
1204 size_t nPos
= Find( rFontData
);
1205 if( nPos
== EXC_FONTLIST_NOTFOUND
)
1207 // not found in buffer - create new font
1208 size_t nSize
= maFontList
.GetSize();
1209 if( nSize
< mnXclMaxSize
)
1211 // possible to insert
1212 maFontList
.AppendNewRecord( new XclExpFont( GetRoot(), rFontData
, eColorType
) );
1213 nPos
= nSize
; // old size is last position now
1217 // buffer is full - ignore new font, use default font
1218 nPos
= EXC_FONT_APP
;
1221 return static_cast< sal_uInt16
>( nPos
);
1224 sal_uInt16
XclExpFontBuffer::Insert(
1225 const SvxFont
& rFont
, XclExpColorType eColorType
)
1227 return Insert( XclFontData( rFont
), eColorType
);
1230 sal_uInt16
XclExpFontBuffer::Insert( const SfxItemSet
& rItemSet
,
1231 sal_Int16 nScript
, XclExpColorType eColorType
, bool bAppFont
)
1233 // #i17050# script type now provided by caller
1234 vcl::Font aFont
= XclExpFontHelper::GetFontFromItemSet( GetRoot(), rItemSet
, nScript
);
1235 return Insert( XclFontData( aFont
), eColorType
, bAppFont
);
1238 void XclExpFontBuffer::Save( XclExpStream
& rStrm
)
1240 maFontList
.Save( rStrm
);
1243 void XclExpFontBuffer::SaveXml( XclExpXmlStream
& rStrm
)
1245 if( maFontList
.IsEmpty() )
1248 sax_fastparser::FSHelperPtr
& rStyleSheet
= rStrm
.GetCurrentStream();
1249 rStyleSheet
->startElement(XML_fonts
, XML_count
, OString::number(maFontList
.GetSize()));
1251 maFontList
.SaveXml( rStrm
);
1253 rStyleSheet
->endElement( XML_fonts
);
1256 // private --------------------------------------------------------------------
1258 void XclExpFontBuffer::InitDefaultFonts()
1260 XclFontData aFontData
;
1261 aFontData
.maName
= "Arial";
1262 aFontData
.SetScFamily( FAMILY_DONTKNOW
);
1263 aFontData
.SetFontEncoding( ScfTools::GetSystemTextEncoding() );
1264 aFontData
.SetScHeight( 200 ); // 200 twips = 10 pt
1265 aFontData
.SetScWeight( WEIGHT_NORMAL
);
1271 maFontList
.AppendNewRecord( new XclExpFont( GetRoot(), aFontData
, EXC_COLOR_CELLTEXT
) );
1272 aFontData
.SetScWeight( WEIGHT_BOLD
);
1273 maFontList
.AppendNewRecord( new XclExpFont( GetRoot(), aFontData
, EXC_COLOR_CELLTEXT
) );
1274 aFontData
.SetScWeight( WEIGHT_NORMAL
);
1275 aFontData
.SetScPosture( ITALIC_NORMAL
);
1276 maFontList
.AppendNewRecord( new XclExpFont( GetRoot(), aFontData
, EXC_COLOR_CELLTEXT
) );
1277 aFontData
.SetScWeight( WEIGHT_BOLD
);
1278 maFontList
.AppendNewRecord( new XclExpFont( GetRoot(), aFontData
, EXC_COLOR_CELLTEXT
) );
1279 // the blind font with index 4
1280 maFontList
.AppendNewRecord( new XclExpBlindFont( GetRoot() ) );
1281 // already add the first user defined font (Excel does it too)
1282 aFontData
.SetScWeight( WEIGHT_NORMAL
);
1283 aFontData
.SetScPosture( ITALIC_NONE
);
1284 maFontList
.AppendNewRecord( new XclExpFont( GetRoot(), aFontData
, EXC_COLOR_CELLTEXT
) );
1289 XclExpFontRef xFont
= new XclExpFont( GetRoot(), aFontData
, EXC_COLOR_CELLTEXT
);
1290 maFontList
.AppendRecord( xFont
);
1291 maFontList
.AppendRecord( xFont
);
1292 maFontList
.AppendRecord( xFont
);
1293 maFontList
.AppendRecord( xFont
);
1294 if( GetOutput() == EXC_OUTPUT_BINARY
)
1295 // the blind font with index 4
1296 maFontList
.AppendNewRecord( new XclExpBlindFont( GetRoot() ) );
1304 size_t XclExpFontBuffer::Find( const XclFontData
& rFontData
)
1306 sal_uInt32 nHash
= lclCalcHash( rFontData
);
1307 for( size_t nPos
= 0, nSize
= maFontList
.GetSize(); nPos
< nSize
; ++nPos
)
1308 if( maFontList
.GetRecord( nPos
)->Equals( rFontData
, nHash
) )
1310 return EXC_FONTLIST_NOTFOUND
;
1313 // FORMAT record - number formats =============================================
1317 /** Predicate for search algorithm. */
1318 struct XclExpNumFmtPred
1320 sal_uInt32 mnScNumFmt
;
1321 explicit XclExpNumFmtPred( sal_uInt32 nScNumFmt
) : mnScNumFmt( nScNumFmt
) {}
1322 bool operator()( const XclExpNumFmt
& rFormat
) const
1323 { return rFormat
.mnScNumFmt
== mnScNumFmt
; }
1328 void XclExpNumFmt::SaveXml( XclExpXmlStream
& rStrm
)
1330 sax_fastparser::FSHelperPtr
& rStyleSheet
= rStrm
.GetCurrentStream();
1331 rStyleSheet
->singleElement( XML_numFmt
,
1332 XML_numFmtId
, OString::number(mnXclNumFmt
),
1333 XML_formatCode
, maNumFmtString
);
1336 XclExpNumFmtBuffer::XclExpNumFmtBuffer( const XclExpRoot
& rRoot
) :
1337 XclExpRoot( rRoot
),
1338 mxFormatter( new SvNumberFormatter( comphelper::getProcessComponentContext(), LANGUAGE_ENGLISH_US
) ),
1339 mpKeywordTable( new NfKeywordTable
),
1340 mnStdFmt( GetFormatter().GetStandardIndex( ScGlobal::eLnge
) )
1344 case EXC_BIFF5
: mnXclOffset
= EXC_FORMAT_OFFSET5
; break;
1345 case EXC_BIFF8
: mnXclOffset
= EXC_FORMAT_OFFSET8
; break;
1346 default: mnXclOffset
= 0; DBG_ERROR_BIFF();
1349 mxFormatter
->FillKeywordTableForExcel( *mpKeywordTable
);
1352 XclExpNumFmtBuffer::~XclExpNumFmtBuffer()
1356 sal_uInt16
XclExpNumFmtBuffer::Insert( sal_uInt32 nScNumFmt
)
1358 XclExpNumFmtVec::const_iterator aIt
=
1359 ::std::find_if( maFormatMap
.begin(), maFormatMap
.end(), XclExpNumFmtPred( nScNumFmt
) );
1360 if( aIt
!= maFormatMap
.end() )
1361 return aIt
->mnXclNumFmt
;
1363 size_t nSize
= maFormatMap
.size();
1364 if( nSize
< o3tl::make_unsigned( 0xFFFF - mnXclOffset
) )
1366 sal_uInt16 nXclNumFmt
= static_cast< sal_uInt16
>( nSize
+ mnXclOffset
);
1367 maFormatMap
.emplace_back( nScNumFmt
, nXclNumFmt
, GetFormatCode( nScNumFmt
) );
1374 void XclExpNumFmtBuffer::Save( XclExpStream
& rStrm
)
1376 for( const auto& rEntry
: maFormatMap
)
1377 WriteFormatRecord( rStrm
, rEntry
);
1380 void XclExpNumFmtBuffer::SaveXml( XclExpXmlStream
& rStrm
)
1382 if( maFormatMap
.empty() )
1385 sax_fastparser::FSHelperPtr
& rStyleSheet
= rStrm
.GetCurrentStream();
1386 rStyleSheet
->startElement(XML_numFmts
, XML_count
, OString::number(maFormatMap
.size()));
1387 for( auto& rEntry
: maFormatMap
)
1389 rEntry
.SaveXml( rStrm
);
1391 rStyleSheet
->endElement( XML_numFmts
);
1394 void XclExpNumFmtBuffer::WriteFormatRecord( XclExpStream
& rStrm
, sal_uInt16 nXclNumFmt
, const OUString
& rFormatStr
)
1396 XclExpString aExpStr
;
1397 if( GetBiff() <= EXC_BIFF5
)
1398 aExpStr
.AssignByte( rFormatStr
, GetTextEncoding(), XclStrFlags::EightBitLength
);
1400 aExpStr
.Assign( rFormatStr
);
1402 rStrm
.StartRecord( EXC_ID4_FORMAT
, 2 + aExpStr
.GetSize() );
1403 rStrm
<< nXclNumFmt
<< aExpStr
;
1407 void XclExpNumFmtBuffer::WriteFormatRecord( XclExpStream
& rStrm
, const XclExpNumFmt
& rFormat
)
1409 WriteFormatRecord( rStrm
, rFormat
.mnXclNumFmt
, GetFormatCode( rFormat
.mnScNumFmt
) );
1414 OUString
GetNumberFormatCode(const XclRoot
& rRoot
, const sal_uInt32 nScNumFmt
, SvNumberFormatter
* pFormatter
, const NfKeywordTable
* pKeywordTable
)
1416 return rRoot
.GetFormatter().GetFormatStringForExcel( nScNumFmt
, *pKeywordTable
, *pFormatter
);
1421 OUString
XclExpNumFmtBuffer::GetFormatCode( sal_uInt32 nScNumFmt
)
1423 return GetNumberFormatCode( *this, nScNumFmt
, mxFormatter
.get(), mpKeywordTable
.get() );
1426 // XF, STYLE record - Cell formatting =========================================
1428 bool XclExpCellProt::FillFromItemSet( const SfxItemSet
& rItemSet
, bool bStyle
)
1430 const ScProtectionAttr
& rProtItem
= rItemSet
.Get( ATTR_PROTECTION
);
1431 mbLocked
= rProtItem
.GetProtection();
1432 mbHidden
= rProtItem
.GetHideFormula() || rProtItem
.GetHideCell();
1433 return ScfTools::CheckItem( rItemSet
, ATTR_PROTECTION
, bStyle
);
1436 void XclExpCellProt::FillToXF3( sal_uInt16
& rnProt
) const
1438 ::set_flag( rnProt
, EXC_XF_LOCKED
, mbLocked
);
1439 ::set_flag( rnProt
, EXC_XF_HIDDEN
, mbHidden
);
1442 void XclExpCellProt::SaveXml( XclExpXmlStream
& rStrm
) const
1444 rStrm
.GetCurrentStream()->singleElement( XML_protection
,
1445 XML_locked
, ToPsz( mbLocked
),
1446 XML_hidden
, ToPsz( mbHidden
) );
1449 bool XclExpCellAlign::FillFromItemSet(const XclRoot
& rRoot
, const SfxItemSet
& rItemSet
,
1450 bool bForceLineBreak
, XclBiff eBiff
, bool bStyle
)
1453 SvxCellHorJustify eHorAlign
= rItemSet
.Get( ATTR_HOR_JUSTIFY
).GetValue();
1454 SvxCellVerJustify eVerAlign
= rItemSet
.Get( ATTR_VER_JUSTIFY
).GetValue();
1458 case EXC_BIFF8
: // attributes new in BIFF8
1461 tools::Long nTmpIndent
= rItemSet
.Get( ATTR_INDENT
).GetValue(); // already in twips
1462 tools::Long nSpaceWidth
= rRoot
.GetSpaceWidth();
1463 sal_Int32 nIndent
= static_cast<double>(nTmpIndent
) / (3.0 * nSpaceWidth
) + 0.5;
1464 mnIndent
= limit_cast
< sal_uInt8
>( nIndent
, 0, 15 );
1465 bUsed
|= ScfTools::CheckItem( rItemSet
, ATTR_INDENT
, bStyle
);
1468 mbShrink
= rItemSet
.Get( ATTR_SHRINKTOFIT
).GetValue();
1469 bUsed
|= ScfTools::CheckItem( rItemSet
, ATTR_SHRINKTOFIT
, bStyle
);
1471 // CTL text direction
1472 SetScFrameDir( rItemSet
.Get( ATTR_WRITINGDIR
).GetValue() );
1473 bUsed
|= ScfTools::CheckItem( rItemSet
, ATTR_WRITINGDIR
, bStyle
);
1478 case EXC_BIFF5
: // attributes new in BIFF5
1479 case EXC_BIFF4
: // attributes new in BIFF4
1481 // vertical alignment
1482 SetScVerAlign( eVerAlign
);
1483 bUsed
|= ScfTools::CheckItem( rItemSet
, ATTR_VER_JUSTIFY
, bStyle
);
1486 bool bStacked
= rItemSet
.Get( ATTR_STACKED
).GetValue();
1487 bUsed
|= ScfTools::CheckItem( rItemSet
, ATTR_STACKED
, bStyle
);
1490 mnRotation
= EXC_ROT_STACKED
;
1495 Degree100 nScRot
= rItemSet
.Get( ATTR_ROTATE_VALUE
).GetValue();
1496 mnRotation
= XclTools::GetXclRotation( nScRot
);
1497 bUsed
|= ScfTools::CheckItem( rItemSet
, ATTR_ROTATE_VALUE
, bStyle
);
1499 mnOrient
= XclTools::GetXclOrientFromRot( mnRotation
);
1504 case EXC_BIFF3
: // attributes new in BIFF3
1507 mbLineBreak
= bForceLineBreak
|| rItemSet
.Get( ATTR_LINEBREAK
).GetValue();
1508 bUsed
|= bForceLineBreak
|| ScfTools::CheckItem( rItemSet
, ATTR_LINEBREAK
, bStyle
);
1513 case EXC_BIFF2
: // attributes new in BIFF2
1515 // horizontal alignment
1516 SetScHorAlign( eHorAlign
);
1517 bUsed
|= ScfTools::CheckItem( rItemSet
, ATTR_HOR_JUSTIFY
, bStyle
);
1521 default: DBG_ERROR_BIFF();
1524 if (eBiff
== EXC_BIFF8
)
1526 // Adjust for distributed alignments.
1527 if (eHorAlign
== SvxCellHorJustify::Block
)
1529 SvxCellJustifyMethod eHorJustMethod
=
1530 rItemSet
.GetItem
<SvxJustifyMethodItem
>(ATTR_HOR_JUSTIFY_METHOD
)->GetValue();
1531 if (eHorJustMethod
== SvxCellJustifyMethod::Distribute
)
1532 mnHorAlign
= EXC_XF_HOR_DISTRIB
;
1535 if (eVerAlign
== SvxCellVerJustify::Block
)
1537 SvxCellJustifyMethod eVerJustMethod
=
1538 rItemSet
.GetItem
<SvxJustifyMethodItem
>(ATTR_VER_JUSTIFY_METHOD
)->GetValue();
1539 if (eVerJustMethod
== SvxCellJustifyMethod::Distribute
)
1540 mnVerAlign
= EXC_XF_VER_DISTRIB
;
1547 void XclExpCellAlign::FillToXF5( sal_uInt16
& rnAlign
) const
1549 ::insert_value( rnAlign
, mnHorAlign
, 0, 3 );
1550 ::set_flag( rnAlign
, EXC_XF_LINEBREAK
, mbLineBreak
);
1551 ::insert_value( rnAlign
, mnVerAlign
, 4, 3 );
1552 ::insert_value( rnAlign
, mnOrient
, 8, 2 );
1555 void XclExpCellAlign::FillToXF8( sal_uInt16
& rnAlign
, sal_uInt16
& rnMiscAttrib
) const
1557 ::insert_value( rnAlign
, mnHorAlign
, 0, 3 );
1558 ::set_flag( rnAlign
, EXC_XF_LINEBREAK
, mbLineBreak
);
1559 ::insert_value( rnAlign
, mnVerAlign
, 4, 3 );
1560 ::insert_value( rnAlign
, mnRotation
, 8, 8 );
1561 ::insert_value( rnMiscAttrib
, mnIndent
, 0, 4 );
1562 ::set_flag( rnMiscAttrib
, EXC_XF8_SHRINK
, mbShrink
);
1563 ::insert_value( rnMiscAttrib
, mnTextDir
, 6, 2 );
1566 static const char* ToHorizontalAlignment( sal_uInt8 nHorAlign
)
1570 case EXC_XF_HOR_GENERAL
: return "general";
1571 case EXC_XF_HOR_LEFT
: return "left";
1572 case EXC_XF_HOR_CENTER
: return "center";
1573 case EXC_XF_HOR_RIGHT
: return "right";
1574 case EXC_XF_HOR_FILL
: return "fill";
1575 case EXC_XF_HOR_JUSTIFY
: return "justify";
1576 case EXC_XF_HOR_CENTER_AS
: return "centerContinuous";
1577 case EXC_XF_HOR_DISTRIB
: return "distributed";
1582 static const char* ToVerticalAlignment( sal_uInt8 nVerAlign
)
1586 case EXC_XF_VER_TOP
: return "top";
1587 case EXC_XF_VER_CENTER
: return "center";
1588 case EXC_XF_VER_BOTTOM
: return "bottom";
1589 case EXC_XF_VER_JUSTIFY
: return "justify";
1590 case EXC_XF_VER_DISTRIB
: return "distributed";
1595 void XclExpCellAlign::SaveXml( XclExpXmlStream
& rStrm
) const
1597 rStrm
.GetCurrentStream()->singleElement( XML_alignment
,
1598 XML_horizontal
, ToHorizontalAlignment( mnHorAlign
),
1599 XML_vertical
, ToVerticalAlignment( mnVerAlign
),
1600 XML_textRotation
, OString::number(mnRotation
),
1601 XML_wrapText
, ToPsz( mbLineBreak
),
1602 XML_indent
, OString::number(mnIndent
),
1603 // OOXTODO: XML_relativeIndent, mnIndent?
1604 // OOXTODO: XML_justifyLastLine,
1605 XML_shrinkToFit
, ToPsz( mbShrink
),
1606 XML_readingOrder
, sax_fastparser::UseIf(OString::number(mnTextDir
), mnTextDir
!= EXC_XF_TEXTDIR_CONTEXT
) );
1611 void lclGetBorderLine(
1612 sal_uInt8
& rnXclLine
, sal_uInt32
& rnColorId
,
1613 const ::editeng::SvxBorderLine
* pLine
, XclExpPalette
& rPalette
, XclBiff eBiff
)
1615 // Document: sc/qa/unit/data/README.cellborders
1617 enum CalcLineIndex
{Idx_None
, Idx_Solid
, Idx_Dotted
, Idx_Dashed
, Idx_FineDashed
, Idx_DashDot
, Idx_DashDotDot
, Idx_DoubleThin
, Idx_Last
};
1618 enum ExcelWidthIndex
{Width_Hair
, Width_Thin
, Width_Medium
, Width_Thick
, Width_Last
};
1619 static sal_uInt8 Map_LineLO_toMS
[Idx_Last
][Width_Last
] =
1621 // 0,05 - 0,74 0,75 - 1,49 1,50 - 2,49 2,50 - 9,00 Width Range [pt]
1622 // EXC_BORDER_HAIR EXC_BORDER_THIN EXC_BORDER_MEDIUM EXC_BORDER_THICK MS Width
1623 {EXC_LINE_NONE
, EXC_LINE_NONE
, EXC_LINE_NONE
, EXC_LINE_NONE
}, // 0 BorderLineStyle::NONE
1624 {EXC_LINE_HAIR
, EXC_LINE_THIN
, EXC_LINE_MEDIUM
, EXC_LINE_THICK
}, // 1 BorderLineStyle::SOLID
1625 {EXC_LINE_DOTTED
, EXC_LINE_DOTTED
, EXC_LINE_MEDIUM_SLANT_DASHDOT
, EXC_LINE_MEDIUM_SLANT_DASHDOT
}, // 2 BorderLineStyle::DOTTED
1626 {EXC_LINE_DOTTED
, EXC_LINE_DASHED
, EXC_LINE_MEDIUM_DASHED
, EXC_LINE_MEDIUM_DASHED
}, // 3 BorderLineStyle::DASHED
1627 {EXC_LINE_DASHED
, EXC_LINE_DASHED
, EXC_LINE_MEDIUM_SLANT_DASHDOT
, EXC_LINE_MEDIUM_SLANT_DASHDOT
}, // 4 BorderLineStyle::FINE_DASHED
1628 {EXC_LINE_DASHED
, EXC_LINE_THIN_DASHDOT
, EXC_LINE_MEDIUM_DASHDOT
, EXC_LINE_MEDIUM_DASHDOT
}, // 5 BorderLineStyle::DASH_DOT
1629 {EXC_LINE_DASHED
, EXC_LINE_THIN_DASHDOTDOT
, EXC_LINE_MEDIUM_DASHDOTDOT
, EXC_LINE_MEDIUM_DASHDOTDOT
}, // 6 BorderLineStyle::DASH_DOT_DOT
1630 {EXC_LINE_DOUBLE
, EXC_LINE_DOUBLE
, EXC_LINE_DOUBLE
, EXC_LINE_DOUBLE
} // 7 BorderLineStyle::DOUBLE_THIN
1633 rnXclLine
= EXC_LINE_NONE
;
1636 sal_uInt16 nOuterWidth
= pLine
->GetOutWidth();
1637 ExcelWidthIndex nOuterWidthIndx
;
1638 CalcLineIndex nStyleIndex
;
1640 switch (pLine
->GetBorderLineStyle())
1642 case SvxBorderLineStyle::NONE
:
1643 nStyleIndex
= Idx_None
;
1645 case SvxBorderLineStyle::SOLID
:
1646 nStyleIndex
= Idx_Solid
;
1648 case SvxBorderLineStyle::DOTTED
:
1649 nStyleIndex
= Idx_Dotted
;
1651 case SvxBorderLineStyle::DASHED
:
1652 nStyleIndex
= Idx_Dashed
;
1654 case SvxBorderLineStyle::FINE_DASHED
:
1655 nStyleIndex
= Idx_FineDashed
;
1657 case SvxBorderLineStyle::DASH_DOT
:
1658 nStyleIndex
= Idx_DashDot
;
1660 case SvxBorderLineStyle::DASH_DOT_DOT
:
1661 nStyleIndex
= Idx_DashDotDot
;
1663 case SvxBorderLineStyle::DOUBLE_THIN
:
1664 // the "nOuterWidth" is not right for this line type
1665 // but at the moment width it not important for that
1666 // the right function is nOuterWidth = (sal_uInt16) pLine->GetWidth();
1667 nStyleIndex
= Idx_DoubleThin
;
1670 nStyleIndex
= Idx_Solid
;
1673 if( nOuterWidth
>= EXC_BORDER_THICK
)
1674 nOuterWidthIndx
= Width_Thick
;
1675 else if( nOuterWidth
>= EXC_BORDER_MEDIUM
)
1676 nOuterWidthIndx
= Width_Medium
;
1677 else if( nOuterWidth
>= EXC_BORDER_THIN
)
1678 nOuterWidthIndx
= Width_Thin
;
1679 else if ( nOuterWidth
>= EXC_BORDER_HAIR
)
1680 nOuterWidthIndx
= Width_Hair
;
1682 nOuterWidthIndx
= Width_Thin
;
1684 rnXclLine
= Map_LineLO_toMS
[nStyleIndex
][nOuterWidthIndx
];
1687 if( (eBiff
== EXC_BIFF2
) && (rnXclLine
!= EXC_LINE_NONE
) )
1688 rnXclLine
= EXC_LINE_THIN
;
1690 rnColorId
= (pLine
&& (rnXclLine
!= EXC_LINE_NONE
)) ?
1691 rPalette
.InsertColor( pLine
->GetColor(), EXC_COLOR_CELLBORDER
) :
1692 XclExpPalette::GetColorIdFromIndex( 0 );
1697 XclExpCellBorder::XclExpCellBorder() :
1698 mnLeftColorId( XclExpPalette::GetColorIdFromIndex( mnLeftColor
) ),
1699 mnRightColorId( XclExpPalette::GetColorIdFromIndex( mnRightColor
) ),
1700 mnTopColorId( XclExpPalette::GetColorIdFromIndex( mnTopColor
) ),
1701 mnBottomColorId( XclExpPalette::GetColorIdFromIndex( mnBottomColor
) ),
1702 mnDiagColorId( XclExpPalette::GetColorIdFromIndex( mnDiagColor
) )
1706 bool XclExpCellBorder::FillFromItemSet(
1707 const SfxItemSet
& rItemSet
, XclExpPalette
& rPalette
, XclBiff eBiff
, bool bStyle
)
1713 case EXC_BIFF8
: // attributes new in BIFF8
1715 const SvxLineItem
& rTLBRItem
= rItemSet
.Get( ATTR_BORDER_TLBR
);
1716 sal_uInt8 nTLBRLine
;
1717 sal_uInt32 nTLBRColorId
;
1718 lclGetBorderLine( nTLBRLine
, nTLBRColorId
, rTLBRItem
.GetLine(), rPalette
, eBiff
);
1719 mbDiagTLtoBR
= (nTLBRLine
!= EXC_LINE_NONE
);
1721 const SvxLineItem
& rBLTRItem
= rItemSet
.Get( ATTR_BORDER_BLTR
);
1722 sal_uInt8 nBLTRLine
;
1723 sal_uInt32 nBLTRColorId
;
1724 lclGetBorderLine( nBLTRLine
, nBLTRColorId
, rBLTRItem
.GetLine(), rPalette
, eBiff
);
1725 mbDiagBLtoTR
= (nBLTRLine
!= EXC_LINE_NONE
);
1727 if( ::ScHasPriority( rTLBRItem
.GetLine(), rBLTRItem
.GetLine() ) )
1729 mnDiagLine
= nTLBRLine
;
1730 mnDiagColorId
= nTLBRColorId
;
1734 mnDiagLine
= nBLTRLine
;
1735 mnDiagColorId
= nBLTRColorId
;
1738 bUsed
|= ScfTools::CheckItem( rItemSet
, ATTR_BORDER_TLBR
, bStyle
) ||
1739 ScfTools::CheckItem( rItemSet
, ATTR_BORDER_BLTR
, bStyle
);
1749 const SvxBoxItem
& rBoxItem
= rItemSet
.Get( ATTR_BORDER
);
1750 lclGetBorderLine( mnLeftLine
, mnLeftColorId
, rBoxItem
.GetLeft(), rPalette
, eBiff
);
1751 lclGetBorderLine( mnRightLine
, mnRightColorId
, rBoxItem
.GetRight(), rPalette
, eBiff
);
1752 lclGetBorderLine( mnTopLine
, mnTopColorId
, rBoxItem
.GetTop(), rPalette
, eBiff
);
1753 lclGetBorderLine( mnBottomLine
, mnBottomColorId
, rBoxItem
.GetBottom(), rPalette
, eBiff
);
1754 bUsed
|= ScfTools::CheckItem( rItemSet
, ATTR_BORDER
, bStyle
);
1758 default: DBG_ERROR_BIFF();
1764 void XclExpCellBorder::SetFinalColors( const XclExpPalette
& rPalette
)
1766 mnLeftColor
= rPalette
.GetColorIndex( mnLeftColorId
);
1767 mnRightColor
= rPalette
.GetColorIndex( mnRightColorId
);
1768 mnTopColor
= rPalette
.GetColorIndex( mnTopColorId
);
1769 mnBottomColor
= rPalette
.GetColorIndex( mnBottomColorId
);
1770 mnDiagColor
= rPalette
.GetColorIndex( mnDiagColorId
);
1773 void XclExpCellBorder::FillToXF5( sal_uInt32
& rnBorder
, sal_uInt32
& rnArea
) const
1775 ::insert_value( rnBorder
, mnTopLine
, 0, 3 );
1776 ::insert_value( rnBorder
, mnLeftLine
, 3, 3 );
1777 ::insert_value( rnArea
, mnBottomLine
, 22, 3 );
1778 ::insert_value( rnBorder
, mnRightLine
, 6, 3 );
1779 ::insert_value( rnBorder
, mnTopColor
, 9, 7 );
1780 ::insert_value( rnBorder
, mnLeftColor
, 16, 7 );
1781 ::insert_value( rnArea
, mnBottomColor
, 25, 7 );
1782 ::insert_value( rnBorder
, mnRightColor
, 23, 7 );
1785 void XclExpCellBorder::FillToXF8( sal_uInt32
& rnBorder1
, sal_uInt32
& rnBorder2
) const
1787 ::insert_value( rnBorder1
, mnLeftLine
, 0, 4 );
1788 ::insert_value( rnBorder1
, mnRightLine
, 4, 4 );
1789 ::insert_value( rnBorder1
, mnTopLine
, 8, 4 );
1790 ::insert_value( rnBorder1
, mnBottomLine
, 12, 4 );
1791 ::insert_value( rnBorder1
, mnLeftColor
, 16, 7 );
1792 ::insert_value( rnBorder1
, mnRightColor
, 23, 7 );
1793 ::insert_value( rnBorder2
, mnTopColor
, 0, 7 );
1794 ::insert_value( rnBorder2
, mnBottomColor
, 7, 7 );
1795 ::insert_value( rnBorder2
, mnDiagColor
, 14, 7 );
1796 ::insert_value( rnBorder2
, mnDiagLine
, 21, 4 );
1797 ::set_flag( rnBorder1
, EXC_XF_DIAGONAL_TL_TO_BR
, mbDiagTLtoBR
);
1798 ::set_flag( rnBorder1
, EXC_XF_DIAGONAL_BL_TO_TR
, mbDiagBLtoTR
);
1801 void XclExpCellBorder::FillToCF8( sal_uInt16
& rnLine
, sal_uInt32
& rnColor
) const
1803 ::insert_value( rnLine
, mnLeftLine
, 0, 4 );
1804 ::insert_value( rnLine
, mnRightLine
, 4, 4 );
1805 ::insert_value( rnLine
, mnTopLine
, 8, 4 );
1806 ::insert_value( rnLine
, mnBottomLine
, 12, 4 );
1807 ::insert_value( rnColor
, mnLeftColor
, 0, 7 );
1808 ::insert_value( rnColor
, mnRightColor
, 7, 7 );
1809 ::insert_value( rnColor
, mnTopColor
, 16, 7 );
1810 ::insert_value( rnColor
, mnBottomColor
, 23, 7 );
1813 static const char* ToLineStyle( sal_uInt8 nLineStyle
)
1815 switch( nLineStyle
)
1817 case EXC_LINE_NONE
: return "none";
1818 case EXC_LINE_THIN
: return "thin";
1819 case EXC_LINE_MEDIUM
: return "medium";
1820 case EXC_LINE_THICK
: return "thick";
1821 case EXC_LINE_DOUBLE
: return "double";
1822 case EXC_LINE_HAIR
: return "hair";
1823 case EXC_LINE_DOTTED
: return "dotted";
1824 case EXC_LINE_DASHED
: return "dashed";
1825 case EXC_LINE_MEDIUM_DASHED
: return "mediumDashed";
1826 case EXC_LINE_THIN_DASHDOT
: return "dashDot";
1827 case EXC_LINE_THIN_DASHDOTDOT
: return "dashDotDot";
1828 case EXC_LINE_MEDIUM_DASHDOT
: return "mediumDashDot";
1829 case EXC_LINE_MEDIUM_DASHDOTDOT
: return "mediumDashDotDot";
1830 case EXC_LINE_MEDIUM_SLANT_DASHDOT
: return "slantDashDot";
1835 static void lcl_WriteBorder( XclExpXmlStream
& rStrm
, sal_Int32 nElement
, sal_uInt8 nLineStyle
, const Color
& rColor
)
1837 sax_fastparser::FSHelperPtr
& rStyleSheet
= rStrm
.GetCurrentStream();
1838 if( nLineStyle
== EXC_LINE_NONE
)
1839 rStyleSheet
->singleElement(nElement
);
1840 else if( rColor
== Color( 0, 0, 0 ) )
1841 rStyleSheet
->singleElement(nElement
, XML_style
, ToLineStyle(nLineStyle
));
1844 rStyleSheet
->startElement(nElement
, XML_style
, ToLineStyle(nLineStyle
));
1845 rStyleSheet
->singleElement(XML_color
, XML_rgb
, XclXmlUtils::ToOString(rColor
));
1846 rStyleSheet
->endElement( nElement
);
1850 void XclExpCellBorder::SaveXml( XclExpXmlStream
& rStrm
) const
1852 sax_fastparser::FSHelperPtr
& rStyleSheet
= rStrm
.GetCurrentStream();
1854 XclExpPalette
& rPalette
= rStrm
.GetRoot().GetPalette();
1856 rStyleSheet
->startElement( XML_border
,
1857 XML_diagonalUp
, ToPsz( mbDiagBLtoTR
),
1858 XML_diagonalDown
, ToPsz( mbDiagTLtoBR
)
1859 // OOXTODO: XML_outline
1861 lcl_WriteBorder( rStrm
, XML_left
, mnLeftLine
, rPalette
.GetColor( mnLeftColor
) );
1862 lcl_WriteBorder( rStrm
, XML_right
, mnRightLine
, rPalette
.GetColor( mnRightColor
) );
1863 lcl_WriteBorder( rStrm
, XML_top
, mnTopLine
, rPalette
.GetColor( mnTopColor
) );
1864 lcl_WriteBorder( rStrm
, XML_bottom
, mnBottomLine
, rPalette
.GetColor( mnBottomColor
) );
1865 lcl_WriteBorder( rStrm
, XML_diagonal
, mnDiagLine
, rPalette
.GetColor( mnDiagColor
) );
1866 // OOXTODO: XML_vertical, XML_horizontal
1867 rStyleSheet
->endElement( XML_border
);
1870 XclExpCellArea::XclExpCellArea() :
1871 mnForeColorId( XclExpPalette::GetColorIdFromIndex( mnForeColor
) ),
1872 mnBackColorId( XclExpPalette::GetColorIdFromIndex( mnBackColor
) ),
1878 XclExpCellArea::XclExpCellArea(Color aForeColor
, Color aBackColor
)
1879 : XclCellArea(EXC_PATT_SOLID
)
1882 , maForeColor(aForeColor
)
1883 , maBackColor(aBackColor
)
1887 bool XclExpCellArea::FillFromItemSet( const SfxItemSet
& rItemSet
, XclExpPalette
& rPalette
, bool bStyle
)
1889 const SvxBrushItem
& rBrushItem
= rItemSet
.Get( ATTR_BACKGROUND
);
1890 if( rBrushItem
.GetColor().IsTransparent() )
1892 mnPattern
= EXC_PATT_NONE
;
1893 mnForeColorId
= XclExpPalette::GetColorIdFromIndex( EXC_COLOR_WINDOWTEXT
);
1894 mnBackColorId
= XclExpPalette::GetColorIdFromIndex( EXC_COLOR_WINDOWBACK
);
1898 mnPattern
= EXC_PATT_SOLID
;
1899 mnForeColorId
= rPalette
.InsertColor( rBrushItem
.GetColor(), EXC_COLOR_CELLAREA
);
1900 mnBackColorId
= XclExpPalette::GetColorIdFromIndex( EXC_COLOR_WINDOWTEXT
);
1902 return ScfTools::CheckItem( rItemSet
, ATTR_BACKGROUND
, bStyle
);
1905 void XclExpCellArea::SetFinalColors( const XclExpPalette
& rPalette
)
1907 rPalette
.GetMixedColors( mnForeColor
, mnBackColor
, mnPattern
, mnForeColorId
, mnBackColorId
);
1910 void XclExpCellArea::FillToXF5( sal_uInt32
& rnArea
) const
1912 ::insert_value( rnArea
, mnPattern
, 16, 6 );
1913 ::insert_value( rnArea
, mnForeColor
, 0, 7 );
1914 ::insert_value( rnArea
, mnBackColor
, 7, 7 );
1917 void XclExpCellArea::FillToXF8( sal_uInt32
& rnBorder2
, sal_uInt16
& rnArea
) const
1919 ::insert_value( rnBorder2
, mnPattern
, 26, 6 );
1920 ::insert_value( rnArea
, mnForeColor
, 0, 7 );
1921 ::insert_value( rnArea
, mnBackColor
, 7, 7 );
1924 void XclExpCellArea::FillToCF8( sal_uInt16
& rnPattern
, sal_uInt16
& rnColor
) const
1926 XclCellArea
aTmp( *this );
1927 if( !aTmp
.IsTransparent() && (aTmp
.mnBackColor
== EXC_COLOR_WINDOWTEXT
) )
1928 aTmp
.mnBackColor
= 0;
1929 if( aTmp
.mnPattern
== EXC_PATT_SOLID
)
1930 ::std::swap( aTmp
.mnForeColor
, aTmp
.mnBackColor
);
1931 ::insert_value( rnColor
, aTmp
.mnForeColor
, 0, 7 );
1932 ::insert_value( rnColor
, aTmp
.mnBackColor
, 7, 7 );
1933 ::insert_value( rnPattern
, aTmp
.mnPattern
, 10, 6 );
1936 static const char* ToPatternType( sal_uInt8 nPattern
)
1940 case EXC_PATT_NONE
: return "none";
1941 case EXC_PATT_SOLID
: return "solid";
1942 case EXC_PATT_50_PERC
: return "mediumGray";
1943 case EXC_PATT_75_PERC
: return "darkGray";
1944 case EXC_PATT_25_PERC
: return "lightGray";
1945 case EXC_PATT_12_5_PERC
: return "gray125";
1946 case EXC_PATT_6_25_PERC
: return "gray0625";
1951 void XclExpCellArea::SaveXml( XclExpXmlStream
& rStrm
) const
1953 sax_fastparser::FSHelperPtr
& rStyleSheet
= rStrm
.GetCurrentStream();
1954 rStyleSheet
->startElement(XML_fill
);
1956 // OOXTODO: XML_gradientFill
1958 XclExpPalette
& rPalette
= rStrm
.GetRoot().GetPalette();
1960 if (mnPattern
== EXC_PATT_NONE
1961 || (mnForeColor
== 0 && mnBackColor
== 0 && maForeColor
== 0 && maBackColor
== 0))
1963 rStyleSheet
->singleElement(XML_patternFill
, XML_patternType
, ToPatternType(mnPattern
));
1967 rStyleSheet
->startElement(XML_patternFill
, XML_patternType
, ToPatternType(mnPattern
));
1968 if (maForeColor
!= 0 || maBackColor
!= 0)
1970 if (maForeColor
!= 0)
1972 rStyleSheet
->singleElement(XML_fgColor
, XML_rgb
,
1973 XclXmlUtils::ToOString(maForeColor
));
1976 if (maBackColor
!= 0)
1978 rStyleSheet
->singleElement(XML_bgColor
, XML_rgb
,
1979 XclXmlUtils::ToOString(maBackColor
));
1984 if (mnForeColor
!= 0)
1986 rStyleSheet
->singleElement(XML_fgColor
, XML_rgb
,
1987 XclXmlUtils::ToOString(rPalette
.GetColor(mnForeColor
)));
1989 if (mnBackColor
!= 0)
1991 rStyleSheet
->singleElement(XML_bgColor
, XML_rgb
,
1992 XclXmlUtils::ToOString(rPalette
.GetColor(mnBackColor
)));
1996 rStyleSheet
->endElement( XML_patternFill
);
1999 rStyleSheet
->endElement( XML_fill
);
2002 bool XclExpColor::FillFromItemSet( const SfxItemSet
& rItemSet
)
2004 if( !ScfTools::CheckItem( rItemSet
, ATTR_BACKGROUND
, true ) )
2007 const SvxBrushItem
& rBrushItem
= rItemSet
.Get( ATTR_BACKGROUND
);
2008 maColor
= rBrushItem
.GetColor();
2013 void XclExpColor::SaveXml( XclExpXmlStream
& rStrm
) const
2015 sax_fastparser::FSHelperPtr
& rStyleSheet
= rStrm
.GetCurrentStream();
2016 rStyleSheet
->startElement(XML_fill
);
2017 rStyleSheet
->startElement(XML_patternFill
);
2018 rStyleSheet
->singleElement(XML_bgColor
, XML_rgb
, XclXmlUtils::ToOString(maColor
));
2020 rStyleSheet
->endElement( XML_patternFill
);
2021 rStyleSheet
->endElement( XML_fill
);
2024 XclExpXFId::XclExpXFId() :
2025 mnXFId( XclExpXFBuffer::GetDefCellXFId() ),
2026 mnXFIndex( EXC_XF_DEFAULTCELL
)
2030 void XclExpXFId::ConvertXFIndex( const XclExpRoot
& rRoot
)
2032 mnXFIndex
= rRoot
.GetXFBuffer().GetXFIndex( mnXFId
);
2036 const XclExpRoot
& rRoot
, const ScPatternAttr
& rPattern
, sal_Int16 nScript
,
2037 sal_uInt32 nForceScNumFmt
, sal_uInt16 nForceXclFont
, bool bForceLineBreak
) :
2041 mnParentXFId
= GetXFBuffer().InsertStyle( rPattern
.GetStyleSheet() );
2042 Init( rPattern
.GetItemSet(), nScript
, nForceScNumFmt
, nForceXclFont
, bForceLineBreak
, false );
2045 XclExpXF::XclExpXF( const XclExpRoot
& rRoot
, const SfxStyleSheetBase
& rStyleSheet
) :
2047 XclExpRoot( rRoot
),
2048 mnParentXFId( XclExpXFBuffer::GetXFIdFromIndex( EXC_XF_STYLEPARENT
) )
2050 bool bDefStyle
= (rStyleSheet
.GetName() == ScResId( STR_STYLENAME_STANDARD
));
2051 sal_Int16 nScript
= bDefStyle
? GetDefApiScript() : css::i18n::ScriptType::WEAK
;
2052 Init( const_cast< SfxStyleSheetBase
& >( rStyleSheet
).GetItemSet(), nScript
,
2053 NUMBERFORMAT_ENTRY_NOT_FOUND
, EXC_FONT_NOTFOUND
, false, bDefStyle
);
2056 XclExpXF::XclExpXF( const XclExpRoot
& rRoot
, bool bCellXF
) :
2057 XclXFBase( bCellXF
),
2058 XclExpRoot( rRoot
),
2059 mnParentXFId( XclExpXFBuffer::GetXFIdFromIndex( EXC_XF_STYLEPARENT
) )
2064 bool XclExpXF::Equals( const ScPatternAttr
& rPattern
,
2065 sal_uInt32 nForceScNumFmt
, sal_uInt16 nForceXclFont
, bool bForceLineBreak
) const
2067 return IsCellXF() && (mpItemSet
== &rPattern
.GetItemSet()) &&
2068 (!bForceLineBreak
|| maAlignment
.mbLineBreak
) &&
2069 ((nForceScNumFmt
== NUMBERFORMAT_ENTRY_NOT_FOUND
) || (mnScNumFmt
== nForceScNumFmt
)) &&
2070 ((nForceXclFont
== EXC_FONT_NOTFOUND
) || (mnXclFont
== nForceXclFont
));
2073 bool XclExpXF::Equals( const SfxStyleSheetBase
& rStyleSheet
) const
2075 return IsStyleXF() && (mpItemSet
== &const_cast< SfxStyleSheetBase
& >( rStyleSheet
).GetItemSet());
2078 void XclExpXF::SetFinalColors()
2080 maBorder
.SetFinalColors( GetPalette() );
2081 maArea
.SetFinalColors( GetPalette() );
2084 bool XclExpXF::Equals( const XclExpXF
& rCmpXF
) const
2086 return XclXFBase::Equals( rCmpXF
) &&
2087 (maProtection
== rCmpXF
.maProtection
) && (maAlignment
== rCmpXF
.maAlignment
) &&
2088 (maBorder
== rCmpXF
.maBorder
) && (maArea
== rCmpXF
.maArea
) &&
2089 (mnXclFont
== rCmpXF
.mnXclFont
) && (mnXclNumFmt
== rCmpXF
.mnXclNumFmt
) &&
2090 (mnParentXFId
== rCmpXF
.mnParentXFId
);
2093 void XclExpXF::InitDefault()
2095 SetRecHeader( EXC_ID5_XF
, (GetBiff() == EXC_BIFF8
) ? 20 : 16 );
2096 mpItemSet
= nullptr;
2097 mnScNumFmt
= NUMBERFORMAT_ENTRY_NOT_FOUND
;
2098 mnXclFont
= mnXclNumFmt
= 0;
2102 void XclExpXF::Init( const SfxItemSet
& rItemSet
, sal_Int16 nScript
,
2103 sal_uInt32 nForceScNumFmt
, sal_uInt16 nForceXclFont
, bool bForceLineBreak
, bool bDefStyle
)
2106 mpItemSet
= &rItemSet
;
2109 mbProtUsed
= maProtection
.FillFromItemSet( rItemSet
, IsStyleXF() );
2112 if( nForceXclFont
== EXC_FONT_NOTFOUND
)
2114 mnXclFont
= GetFontBuffer().Insert( rItemSet
, nScript
, EXC_COLOR_CELLTEXT
, bDefStyle
);
2115 mbFontUsed
= XclExpFontHelper::CheckItems( GetRoot(), rItemSet
, nScript
, IsStyleXF() );
2119 mnXclFont
= nForceXclFont
;
2124 if (nForceScNumFmt
!= NUMBERFORMAT_ENTRY_NOT_FOUND
)
2125 mnXclNumFmt
= nForceScNumFmt
;
2128 // Built-in formats of dedicated languages may be attributed using the
2129 // system language (or even other?) format with a language attribute,
2130 // obtain the "real" format key.
2131 mnScNumFmt
= rItemSet
.Get( ATTR_VALUE_FORMAT
).GetValue();
2132 LanguageType nLang
= rItemSet
.Get( ATTR_LANGUAGE_FORMAT
).GetLanguage();
2133 if (mnScNumFmt
>= SV_COUNTRY_LANGUAGE_OFFSET
|| nLang
!= LANGUAGE_SYSTEM
)
2134 mnScNumFmt
= GetFormatter().GetFormatForLanguageIfBuiltIn( mnScNumFmt
, nLang
);
2136 mnXclNumFmt
= GetNumFmtBuffer().Insert( mnScNumFmt
);
2137 mbFmtUsed
= ScfTools::CheckItem( rItemSet
, ATTR_VALUE_FORMAT
, IsStyleXF() );
2140 mbAlignUsed
= maAlignment
.FillFromItemSet(*this, rItemSet
, bForceLineBreak
, GetBiff(), IsStyleXF());
2143 mbBorderUsed
= maBorder
.FillFromItemSet( rItemSet
, GetPalette(), GetBiff(), IsStyleXF() );
2146 mbAreaUsed
= maArea
.FillFromItemSet( rItemSet
, GetPalette(), IsStyleXF() );
2148 // set all b***Used flags to true in "Default"/"Normal" style
2150 SetAllUsedFlags( true );
2153 sal_uInt8
XclExpXF::GetUsedFlags() const
2155 sal_uInt8 nUsedFlags
= 0;
2156 /* In cell XFs a set bit means a used attribute, in style XFs a cleared bit.
2157 "mbCellXF == mb***Used" evaluates to correct value in cell and style XFs. */
2158 ::set_flag( nUsedFlags
, EXC_XF_DIFF_PROT
, mbCellXF
== mbProtUsed
);
2159 ::set_flag( nUsedFlags
, EXC_XF_DIFF_FONT
, mbCellXF
== mbFontUsed
);
2160 ::set_flag( nUsedFlags
, EXC_XF_DIFF_VALFMT
, mbCellXF
== mbFmtUsed
);
2161 ::set_flag( nUsedFlags
, EXC_XF_DIFF_ALIGN
, mbCellXF
== mbAlignUsed
);
2162 ::set_flag( nUsedFlags
, EXC_XF_DIFF_BORDER
, mbCellXF
== mbBorderUsed
);
2163 ::set_flag( nUsedFlags
, EXC_XF_DIFF_AREA
, mbCellXF
== mbAreaUsed
);
2167 void XclExpXF::WriteBody5( XclExpStream
& rStrm
)
2169 sal_uInt16 nTypeProt
= 0, nAlign
= 0;
2170 sal_uInt32 nArea
= 0, nBorder
= 0;
2172 ::set_flag( nTypeProt
, EXC_XF_STYLE
, IsStyleXF() );
2173 ::insert_value( nTypeProt
, mnParent
, 4, 12 );
2174 ::insert_value( nAlign
, GetUsedFlags(), 10, 6 );
2176 maProtection
.FillToXF3( nTypeProt
);
2177 maAlignment
.FillToXF5( nAlign
);
2178 maBorder
.FillToXF5( nBorder
, nArea
);
2179 maArea
.FillToXF5( nArea
);
2181 rStrm
<< mnXclFont
<< mnXclNumFmt
<< nTypeProt
<< nAlign
<< nArea
<< nBorder
;
2184 void XclExpXF::WriteBody8( XclExpStream
& rStrm
)
2186 sal_uInt16 nTypeProt
= 0, nAlign
= 0, nMiscAttrib
= 0, nArea
= 0;
2187 sal_uInt32 nBorder1
= 0, nBorder2
= 0;
2189 ::set_flag( nTypeProt
, EXC_XF_STYLE
, IsStyleXF() );
2190 ::insert_value( nTypeProt
, mnParent
, 4, 12 );
2191 ::insert_value( nMiscAttrib
, GetUsedFlags(), 10, 6 );
2193 maProtection
.FillToXF3( nTypeProt
);
2194 maAlignment
.FillToXF8( nAlign
, nMiscAttrib
);
2195 maBorder
.FillToXF8( nBorder1
, nBorder2
);
2196 maArea
.FillToXF8( nBorder2
, nArea
);
2198 rStrm
<< mnXclFont
<< mnXclNumFmt
<< nTypeProt
<< nAlign
<< nMiscAttrib
<< nBorder1
<< nBorder2
<< nArea
;
2201 void XclExpXF::WriteBody( XclExpStream
& rStrm
)
2203 XclExpXFId
aParentId( mnParentXFId
);
2204 aParentId
.ConvertXFIndex( GetRoot() );
2205 mnParent
= aParentId
.mnXFIndex
;
2208 case EXC_BIFF5
: WriteBody5( rStrm
); break;
2209 case EXC_BIFF8
: WriteBody8( rStrm
); break;
2210 default: DBG_ERROR_BIFF();
2214 void XclExpXF::SetXmlIds( sal_uInt32 nBorderId
, sal_uInt32 nFillId
)
2216 mnBorderId
= nBorderId
;
2220 void XclExpXF::SaveXml( XclExpXmlStream
& rStrm
)
2222 sax_fastparser::FSHelperPtr
& rStyleSheet
= rStrm
.GetCurrentStream();
2224 sal_Int32 nXfId
= 0;
2225 const XclExpXF
* pStyleXF
= nullptr;
2228 sal_uInt16 nXFIndex
= rStrm
.GetRoot().GetXFBuffer().GetXFIndex( mnParentXFId
);
2229 nXfId
= rStrm
.GetRoot().GetXFBuffer().GetXmlStyleIndex( nXFIndex
);
2230 pStyleXF
= rStrm
.GetRoot().GetXFBuffer().GetXFById( mnParentXFId
);
2233 rStyleSheet
->startElement( XML_xf
,
2234 XML_numFmtId
, OString::number(mnXclNumFmt
),
2235 XML_fontId
, OString::number(mnXclFont
),
2236 XML_fillId
, OString::number(mnFillId
),
2237 XML_borderId
, OString::number(mnBorderId
),
2238 XML_xfId
, sax_fastparser::UseIf(OString::number(nXfId
), !IsStyleXF()),
2239 // OOXTODO: XML_quotePrefix,
2240 // OOXTODO: XML_pivotButton,
2241 // OOXTODO: XML_applyNumberFormat, ;
2242 XML_applyFont
, ToPsz( mbFontUsed
),
2243 // OOXTODO: XML_applyFill,
2244 XML_applyBorder
, ToPsz( mbBorderUsed
),
2245 XML_applyAlignment
, ToPsz( mbAlignUsed
),
2246 XML_applyProtection
, ToPsz( mbProtUsed
) );
2248 maAlignment
.SaveXml( rStrm
);
2249 else if ( pStyleXF
)
2250 pStyleXF
->GetAlignmentData().SaveXml( rStrm
);
2252 maProtection
.SaveXml( rStrm
);
2253 else if ( pStyleXF
)
2254 pStyleXF
->GetProtectionData().SaveXml( rStrm
);
2256 // OOXTODO: XML_extLst
2257 rStyleSheet
->endElement( XML_xf
);
2260 XclExpDefaultXF::XclExpDefaultXF( const XclExpRoot
& rRoot
, bool bCellXF
) :
2261 XclExpXF( rRoot
, bCellXF
)
2265 void XclExpDefaultXF::SetFont( sal_uInt16 nXclFont
)
2267 mnXclFont
= nXclFont
;
2271 void XclExpDefaultXF::SetNumFmt( sal_uInt16 nXclNumFmt
)
2273 mnXclNumFmt
= nXclNumFmt
;
2277 XclExpStyle::XclExpStyle( sal_uInt32 nXFId
, const OUString
& rStyleName
) :
2278 XclExpRecord( EXC_ID_STYLE
, 4 ),
2279 maName( rStyleName
),
2281 mnStyleId( EXC_STYLE_USERDEF
),
2282 mnLevel( EXC_STYLE_NOLEVEL
)
2284 OSL_ENSURE( !maName
.isEmpty(), "XclExpStyle::XclExpStyle - empty style name" );
2285 #if OSL_DEBUG_LEVEL > 0
2286 sal_uInt8 nStyleId
, nLevel
; // do not use members for debug tests
2287 OSL_ENSURE( !XclTools::GetBuiltInStyleId( nStyleId
, nLevel
, maName
),
2288 "XclExpStyle::XclExpStyle - this is a built-in style" );
2292 XclExpStyle::XclExpStyle( sal_uInt32 nXFId
, sal_uInt8 nStyleId
, sal_uInt8 nLevel
) :
2293 XclExpRecord( EXC_ID_STYLE
, 4 ),
2295 mnStyleId( nStyleId
),
2300 void XclExpStyle::WriteBody( XclExpStream
& rStrm
)
2302 maXFId
.ConvertXFIndex( rStrm
.GetRoot() );
2303 ::set_flag( maXFId
.mnXFIndex
, EXC_STYLE_BUILTIN
, IsBuiltIn() );
2304 rStrm
<< maXFId
.mnXFIndex
;
2308 rStrm
<< mnStyleId
<< mnLevel
;
2312 XclExpString aNameEx
;
2313 if( rStrm
.GetRoot().GetBiff() == EXC_BIFF8
)
2314 aNameEx
.Assign( maName
);
2316 aNameEx
.AssignByte( maName
, rStrm
.GetRoot().GetTextEncoding(), XclStrFlags::EightBitLength
);
2321 static const char* lcl_StyleNameFromId( sal_Int32 nStyleId
)
2325 case 0: return "Normal";
2326 case 3: return "Comma";
2327 case 4: return "Currency";
2328 case 5: return "Percent";
2329 case 6: return "Comma [0]";
2330 case 7: return "Currency [0]";
2335 void XclExpStyle::SaveXml( XclExpXmlStream
& rStrm
)
2337 constexpr sal_Int32 CELL_STYLE_MAX_BUILTIN_ID
= 54;
2340 const char* pBuiltinId
= nullptr;
2343 sName
= OString( lcl_StyleNameFromId( mnStyleId
) );
2344 sBuiltinId
= OString::number( std::min( static_cast<sal_Int32
>( CELL_STYLE_MAX_BUILTIN_ID
- 1 ), static_cast <sal_Int32
>( mnStyleId
) ) );
2345 pBuiltinId
= sBuiltinId
.getStr();
2348 sName
= maName
.toUtf8();
2350 // get the index in sortedlist associated with the mnXId
2351 sal_Int32 nXFId
= rStrm
.GetRoot().GetXFBuffer().GetXFIndex( maXFId
.mnXFId
);
2352 // get the style index associated with index into sortedlist
2353 nXFId
= rStrm
.GetRoot().GetXFBuffer().GetXmlStyleIndex( nXFId
);
2354 rStrm
.GetCurrentStream()->singleElement( XML_cellStyle
,
2356 XML_xfId
, OString::number(nXFId
),
2357 // builtinId of 54 or above is invalid according to OpenXML SDK validator.
2358 XML_builtinId
, pBuiltinId
2359 // OOXTODO: XML_iLevel,
2360 // OOXTODO: XML_hidden,
2361 // XML_customBuiltin, ToPsz( ! IsBuiltIn() )
2363 // OOXTODO: XML_extLst
2368 const sal_uInt32 EXC_XFLIST_INDEXBASE
= 0xFFFE0000;
2369 /** Maximum count of XF records to store in the XF list (performance). */
2370 const sal_uInt32 EXC_XFLIST_HARDLIMIT
= 256 * 1024;
2372 bool lclIsBuiltInStyle( const OUString
& rStyleName
)
2375 XclTools::IsBuiltInStyleName( rStyleName
) ||
2376 XclTools::IsCondFormatStyleName( rStyleName
);
2381 XclExpXFBuffer::XclExpBuiltInInfo::XclExpBuiltInInfo() :
2382 mnStyleId( EXC_STYLE_USERDEF
),
2383 mnLevel( EXC_STYLE_NOLEVEL
),
2384 mbPredefined( true ),
2385 mbHasStyleRec( false )
2391 /** Predicate for search algorithm. */
2392 struct XclExpBorderPred
2394 const XclExpCellBorder
&
2396 explicit XclExpBorderPred( const XclExpCellBorder
& rBorder
) : mrBorder( rBorder
) {}
2397 bool operator()( const XclExpCellBorder
& rBorder
) const;
2402 bool XclExpBorderPred::operator()( const XclExpCellBorder
& rBorder
) const
2405 mrBorder
.mnLeftColor
== rBorder
.mnLeftColor
&&
2406 mrBorder
.mnRightColor
== rBorder
.mnRightColor
&&
2407 mrBorder
.mnTopColor
== rBorder
.mnTopColor
&&
2408 mrBorder
.mnBottomColor
== rBorder
.mnBottomColor
&&
2409 mrBorder
.mnDiagColor
== rBorder
.mnDiagColor
&&
2410 mrBorder
.mnLeftLine
== rBorder
.mnLeftLine
&&
2411 mrBorder
.mnRightLine
== rBorder
.mnRightLine
&&
2412 mrBorder
.mnTopLine
== rBorder
.mnTopLine
&&
2413 mrBorder
.mnBottomLine
== rBorder
.mnBottomLine
&&
2414 mrBorder
.mnDiagLine
== rBorder
.mnDiagLine
&&
2415 mrBorder
.mbDiagTLtoBR
== rBorder
.mbDiagTLtoBR
&&
2416 mrBorder
.mbDiagBLtoTR
== rBorder
.mbDiagBLtoTR
&&
2417 mrBorder
.mnLeftColorId
== rBorder
.mnLeftColorId
&&
2418 mrBorder
.mnRightColorId
== rBorder
.mnRightColorId
&&
2419 mrBorder
.mnTopColorId
== rBorder
.mnTopColorId
&&
2420 mrBorder
.mnBottomColorId
== rBorder
.mnBottomColorId
&&
2421 mrBorder
.mnDiagColorId
== rBorder
.mnDiagColorId
;
2426 struct XclExpFillPred
2428 const XclExpCellArea
&
2430 explicit XclExpFillPred( const XclExpCellArea
& rFill
) : mrFill( rFill
) {}
2431 bool operator()( const XclExpCellArea
& rFill
) const;
2436 bool XclExpFillPred::operator()( const XclExpCellArea
& rFill
) const
2439 mrFill
.mnForeColor
== rFill
.mnForeColor
&&
2440 mrFill
.mnBackColor
== rFill
.mnBackColor
&&
2441 mrFill
.mnPattern
== rFill
.mnPattern
&&
2442 mrFill
.mnForeColorId
== rFill
.mnForeColorId
&&
2443 mrFill
.mnBackColorId
== rFill
.mnBackColorId
;
2446 XclExpXFBuffer::XclExpXFBuffer( const XclExpRoot
& rRoot
) :
2451 void XclExpXFBuffer::Initialize()
2453 InsertDefaultRecords();
2457 sal_uInt32
XclExpXFBuffer::Insert( const ScPatternAttr
* pPattern
, sal_Int16 nScript
)
2459 return InsertCellXF( pPattern
, nScript
, NUMBERFORMAT_ENTRY_NOT_FOUND
, EXC_FONT_NOTFOUND
, false );
2462 sal_uInt32
XclExpXFBuffer::InsertWithFont( const ScPatternAttr
* pPattern
, sal_Int16 nScript
,
2463 sal_uInt16 nForceXclFont
, bool bForceLineBreak
)
2465 return InsertCellXF( pPattern
, nScript
, NUMBERFORMAT_ENTRY_NOT_FOUND
, nForceXclFont
, bForceLineBreak
);
2468 sal_uInt32
XclExpXFBuffer::InsertWithNumFmt( const ScPatternAttr
* pPattern
, sal_Int16 nScript
, sal_uInt32 nForceScNumFmt
, bool bForceLineBreak
)
2470 return InsertCellXF( pPattern
, nScript
, nForceScNumFmt
, EXC_FONT_NOTFOUND
, bForceLineBreak
);
2473 sal_uInt32
XclExpXFBuffer::InsertStyle( const SfxStyleSheetBase
* pStyleSheet
)
2475 return pStyleSheet
? InsertStyleXF( *pStyleSheet
) : GetXFIdFromIndex( EXC_XF_DEFAULTSTYLE
);
2478 sal_uInt32
XclExpXFBuffer::GetXFIdFromIndex( sal_uInt16 nXFIndex
)
2480 return EXC_XFLIST_INDEXBASE
| nXFIndex
;
2483 sal_uInt32
XclExpXFBuffer::GetDefCellXFId()
2485 return GetXFIdFromIndex( EXC_XF_DEFAULTCELL
);
2488 const XclExpXF
* XclExpXFBuffer::GetXFById( sal_uInt32 nXFId
) const
2490 return maXFList
.GetRecord( nXFId
);
2493 void XclExpXFBuffer::Finalize()
2495 for( size_t nPos
= 0, nSize
= maXFList
.GetSize(); nPos
< nSize
; ++nPos
)
2496 maXFList
.GetRecord( nPos
)->SetFinalColors();
2498 sal_uInt32 nTotalCount
= static_cast< sal_uInt32
>( maXFList
.GetSize() );
2500 maXFIndexVec
.resize( nTotalCount
, EXC_XF_DEFAULTCELL
);
2501 maStyleIndexes
.resize( nTotalCount
, EXC_XF_DEFAULTCELL
);
2502 maCellIndexes
.resize( nTotalCount
, EXC_XF_DEFAULTCELL
);
2504 XclExpBuiltInMap::const_iterator aBuiltInEnd
= maBuiltInMap
.end();
2505 /* nMaxBuiltInXFId used to decide faster whether an XF record is
2506 user-defined. If the current XF ID is greater than this value,
2507 maBuiltInMap doesn't need to be searched. */
2508 sal_uInt32 nMaxBuiltInXFId
= maBuiltInMap
.empty() ? 0 : maBuiltInMap
.rbegin()->first
;
2510 // *** map all built-in XF records (cell and style) *** -------------------
2512 // do not change XF order -> std::map<> iterates elements in ascending order
2513 for( const auto& rEntry
: maBuiltInMap
)
2514 AppendXFIndex( rEntry
.first
);
2516 // *** insert all user-defined style XF records, without reduce *** -------
2518 sal_uInt32 nStyleXFCount
= 0; // counts up to EXC_XF_MAXSTYLECOUNT limit
2520 for( nId
= 0; nId
< nTotalCount
; ++nId
)
2522 XclExpXFRef xXF
= maXFList
.GetRecord( nId
);
2523 if( xXF
->IsStyleXF() && ((nId
> nMaxBuiltInXFId
) || (maBuiltInMap
.find( nId
) == aBuiltInEnd
)) )
2525 if( nStyleXFCount
< EXC_XF_MAXSTYLECOUNT
)
2527 // maximum count of styles not reached
2528 AppendXFIndex( nId
);
2533 /* Maximum count of styles reached - do not append more
2534 pointers to XFs; use default style XF instead; do not break
2535 the loop to initialize all maXFIndexVec elements. */
2536 maXFIndexVec
[ nId
] = EXC_XF_DEFAULTSTYLE
;
2541 // *** insert all cell XF records *** -------------------------------------
2543 // start position to search for equal inserted XF records
2544 size_t nSearchStart
= maSortedXFList
.GetSize();
2546 // break the loop if XF limit reached - maXFIndexVec is already initialized with default index
2547 XclExpXFRef xDefCellXF
= maXFList
.GetRecord( EXC_XF_DEFAULTCELL
);
2548 for( nId
= 0; (nId
< nTotalCount
) && (maSortedXFList
.GetSize() < EXC_XF_MAXCOUNT
); ++nId
)
2550 XclExpXFRef xXF
= maXFList
.GetRecord( nId
);
2551 if( xXF
->IsCellXF() && ((nId
> nMaxBuiltInXFId
) || (maBuiltInMap
.find( nId
) == aBuiltInEnd
)) )
2553 // try to find an XF record equal to *xXF, which is already inserted
2554 sal_uInt16 nFoundIndex
= EXC_XF_NOTFOUND
;
2556 // first try if it is equal to the default cell XF
2557 if( xDefCellXF
->Equals( *xXF
) )
2559 nFoundIndex
= EXC_XF_DEFAULTCELL
;
2561 else for( size_t nSearchPos
= nSearchStart
, nSearchEnd
= maSortedXFList
.GetSize();
2562 (nSearchPos
< nSearchEnd
) && (nFoundIndex
== EXC_XF_NOTFOUND
); ++nSearchPos
)
2564 if( maSortedXFList
.GetRecord( nSearchPos
)->Equals( *xXF
) )
2565 nFoundIndex
= static_cast< sal_uInt16
>( nSearchPos
);
2568 if( nFoundIndex
!= EXC_XF_NOTFOUND
)
2569 // equal XF already in the list, use its resulting XF index
2570 maXFIndexVec
[ nId
] = nFoundIndex
;
2572 AppendXFIndex( nId
);
2576 sal_uInt16 nXmlStyleIndex
= 0;
2577 sal_uInt16 nXmlCellIndex
= 0;
2579 size_t nXFCount
= maSortedXFList
.GetSize();
2580 for( size_t i
= 0; i
< nXFCount
; ++i
)
2582 XclExpXFList::RecordRefType xXF
= maSortedXFList
.GetRecord( i
);
2583 if( xXF
->IsStyleXF() )
2584 maStyleIndexes
[ i
] = nXmlStyleIndex
++;
2586 maCellIndexes
[ i
] = nXmlCellIndex
++;
2590 sal_uInt16
XclExpXFBuffer::GetXFIndex( sal_uInt32 nXFId
) const
2592 sal_uInt16 nXFIndex
= EXC_XF_DEFAULTSTYLE
;
2593 if( nXFId
>= EXC_XFLIST_INDEXBASE
)
2594 nXFIndex
= static_cast< sal_uInt16
>( nXFId
& ~EXC_XFLIST_INDEXBASE
);
2595 else if( nXFId
< maXFIndexVec
.size() )
2596 nXFIndex
= maXFIndexVec
[ nXFId
];
2600 sal_Int32
XclExpXFBuffer::GetXmlStyleIndex( sal_uInt32 nXFIndex
) const
2602 OSL_ENSURE( nXFIndex
< maStyleIndexes
.size(), "XclExpXFBuffer::GetXmlStyleIndex - invalid index!" );
2603 if( nXFIndex
>= maStyleIndexes
.size() )
2604 return 0; // should be caught/debugged via above assert; return "valid" index.
2605 return maStyleIndexes
[ nXFIndex
];
2608 sal_Int32
XclExpXFBuffer::GetXmlCellIndex( sal_uInt32 nXFIndex
) const
2610 OSL_ENSURE( nXFIndex
< maCellIndexes
.size(), "XclExpXFBuffer::GetXmlStyleIndex - invalid index!" );
2611 if( nXFIndex
>= maCellIndexes
.size() )
2612 return 0; // should be caught/debugged via above assert; return "valid" index.
2613 return maCellIndexes
[ nXFIndex
];
2616 void XclExpXFBuffer::Save( XclExpStream
& rStrm
)
2618 // save all XF records contained in the maSortedXFList vector (sorted by XF index)
2619 maSortedXFList
.Save( rStrm
);
2620 // save all STYLE records
2621 maStyleList
.Save( rStrm
);
2624 static void lcl_GetCellCounts( const XclExpRecordList
< XclExpXF
>& rXFList
, sal_Int32
& rCells
, sal_Int32
& rStyles
)
2628 size_t nXFCount
= rXFList
.GetSize();
2629 for( size_t i
= 0; i
< nXFCount
; ++i
)
2631 XclExpRecordList
< XclExpXF
>::RecordRefType xXF
= rXFList
.GetRecord( i
);
2632 if( xXF
->IsCellXF() )
2634 else if( xXF
->IsStyleXF() )
2639 void XclExpXFBuffer::SaveXml( XclExpXmlStream
& rStrm
)
2641 sax_fastparser::FSHelperPtr
& rStyleSheet
= rStrm
.GetCurrentStream();
2643 rStyleSheet
->startElement(XML_fills
, XML_count
, OString::number(maFills
.size()));
2644 for( const auto& rFill
: maFills
)
2646 rFill
.SaveXml( rStrm
);
2648 rStyleSheet
->endElement( XML_fills
);
2650 rStyleSheet
->startElement(XML_borders
, XML_count
, OString::number(maBorders
.size()));
2651 for( const auto& rBorder
: maBorders
)
2653 rBorder
.SaveXml( rStrm
);
2655 rStyleSheet
->endElement( XML_borders
);
2657 // save all XF records contained in the maSortedXFList vector (sorted by XF index)
2658 sal_Int32 nCells
, nStyles
;
2659 lcl_GetCellCounts( maSortedXFList
, nCells
, nStyles
);
2663 rStyleSheet
->startElement(XML_cellStyleXfs
, XML_count
, OString::number(nStyles
));
2664 size_t nXFCount
= maSortedXFList
.GetSize();
2665 for( size_t i
= 0; i
< nXFCount
; ++i
)
2667 XclExpXFList::RecordRefType xXF
= maSortedXFList
.GetRecord( i
);
2668 if( ! xXF
->IsStyleXF() )
2670 SaveXFXml( rStrm
, *xXF
);
2672 rStyleSheet
->endElement( XML_cellStyleXfs
);
2677 rStyleSheet
->startElement(XML_cellXfs
, XML_count
, OString::number(nCells
));
2678 size_t nXFCount
= maSortedXFList
.GetSize();
2679 for( size_t i
= 0; i
< nXFCount
; ++i
)
2681 XclExpXFList::RecordRefType xXF
= maSortedXFList
.GetRecord( i
);
2682 if( ! xXF
->IsCellXF() )
2684 SaveXFXml( rStrm
, *xXF
);
2686 rStyleSheet
->endElement( XML_cellXfs
);
2689 // save all STYLE records
2690 rStyleSheet
->startElement(XML_cellStyles
, XML_count
, OString::number(maStyleList
.GetSize()));
2691 maStyleList
.SaveXml( rStrm
);
2692 rStyleSheet
->endElement( XML_cellStyles
);
2695 void XclExpXFBuffer::SaveXFXml( XclExpXmlStream
& rStrm
, XclExpXF
& rXF
)
2697 XclExpBorderList::iterator aBorderPos
=
2698 std::find_if( maBorders
.begin(), maBorders
.end(), XclExpBorderPred( rXF
.GetBorderData() ) );
2699 OSL_ENSURE( aBorderPos
!= maBorders
.end(), "XclExpXFBuffer::SaveXml - Invalid @borderId!" );
2700 XclExpFillList::iterator aFillPos
=
2701 std::find_if( maFills
.begin(), maFills
.end(), XclExpFillPred( rXF
.GetAreaData() ) );
2702 OSL_ENSURE( aFillPos
!= maFills
.end(), "XclExpXFBuffer::SaveXml - Invalid @fillId!" );
2704 sal_Int32 nBorderId
= 0, nFillId
= 0;
2705 if( aBorderPos
!= maBorders
.end() )
2706 nBorderId
= std::distance( maBorders
.begin(), aBorderPos
);
2707 if( aFillPos
!= maFills
.end() )
2708 nFillId
= std::distance( maFills
.begin(), aFillPos
);
2710 rXF
.SetXmlIds( nBorderId
, nFillId
);
2711 rXF
.SaveXml( rStrm
);
2714 sal_uInt32
XclExpXFBuffer::FindXF( const ScPatternAttr
& rPattern
,
2715 sal_uInt32 nForceScNumFmt
, sal_uInt16 nForceXclFont
, bool bForceLineBreak
) const
2717 if (nForceScNumFmt
!= NUMBERFORMAT_ENTRY_NOT_FOUND
&& nForceXclFont
== EXC_FONT_NOTFOUND
)
2719 FindKey key1
{ /*mbCellXF*/true, &rPattern
.GetItemSet(), nForceScNumFmt
, 0 };
2720 FindKey key2
{ /*mbCellXF*/true, &rPattern
.GetItemSet(), nForceScNumFmt
, EXC_FONT_NOTFOUND
};
2721 auto it1
= maXFFindMap
.lower_bound(key1
);
2722 if (it1
!= maXFFindMap
.end())
2724 auto it2
= maXFFindMap
.upper_bound(key2
);
2725 for (auto it
= it1
; it
!= it2
; ++it
)
2726 for (auto const & nPos
: it
->second
)
2727 if( maXFList
.GetRecord( nPos
)->Equals( rPattern
, nForceScNumFmt
, nForceXclFont
, bForceLineBreak
) )
2731 else if (nForceScNumFmt
== NUMBERFORMAT_ENTRY_NOT_FOUND
|| nForceXclFont
== EXC_FONT_NOTFOUND
)
2733 FindKey key1
{ /*mbCellXF*/true, &rPattern
.GetItemSet(), 0, 0 };
2734 FindKey key2
{ /*mbCellXF*/true, &rPattern
.GetItemSet(), NUMBERFORMAT_ENTRY_NOT_FOUND
, EXC_FONT_NOTFOUND
};
2735 auto it1
= maXFFindMap
.lower_bound(key1
);
2736 if (it1
!= maXFFindMap
.end())
2738 auto it2
= maXFFindMap
.upper_bound(key2
);
2739 for (auto it
= it1
; it
!= it2
; ++it
)
2740 for (auto const & nPos
: it
->second
)
2741 if( maXFList
.GetRecord( nPos
)->Equals( rPattern
, nForceScNumFmt
, nForceXclFont
, bForceLineBreak
) )
2747 FindKey key
{ /*mbCellXF*/true, &rPattern
.GetItemSet(), nForceScNumFmt
, nForceXclFont
};
2748 auto it
= maXFFindMap
.find(key
);
2749 if (it
== maXFFindMap
.end())
2750 return EXC_XFID_NOTFOUND
;
2751 for (auto const & nPos
: it
->second
)
2752 if( maXFList
.GetRecord( nPos
)->Equals( rPattern
, nForceScNumFmt
, nForceXclFont
, bForceLineBreak
) )
2755 return EXC_XFID_NOTFOUND
;
2758 sal_uInt32
XclExpXFBuffer::FindXF( const SfxStyleSheetBase
& rStyleSheet
) const
2760 const SfxItemSet
* pItemSet
= &const_cast< SfxStyleSheetBase
& >( rStyleSheet
).GetItemSet();
2761 FindKey key1
{ /*mbCellXF*/false, pItemSet
, 0, 0 };
2762 FindKey key2
{ /*mbCellXF*/false, pItemSet
, NUMBERFORMAT_ENTRY_NOT_FOUND
, EXC_FONT_NOTFOUND
};
2763 auto it1
= maXFFindMap
.lower_bound(key1
);
2764 auto it2
= maXFFindMap
.upper_bound(key2
);
2765 for (auto it
= it1
; it
!= it2
; ++it
)
2766 for (auto const & nPos
: it
->second
)
2767 if( maXFList
.GetRecord( nPos
)->Equals( rStyleSheet
) )
2769 return EXC_XFID_NOTFOUND
;
2772 sal_uInt32
XclExpXFBuffer::FindBuiltInXF( sal_uInt8 nStyleId
, sal_uInt8 nLevel
) const
2774 auto aIt
= std::find_if(maBuiltInMap
.begin(), maBuiltInMap
.end(),
2775 [&nStyleId
, nLevel
](const XclExpBuiltInMap::value_type
& rEntry
) {
2776 return (rEntry
.second
.mnStyleId
== nStyleId
) && (rEntry
.second
.mnLevel
== nLevel
);
2778 if (aIt
!= maBuiltInMap
.end())
2780 return EXC_XFID_NOTFOUND
;
2783 XclExpXFBuffer::FindKey
XclExpXFBuffer::ToFindKey(XclExpXF
const & rRec
)
2785 return { rRec
.IsCellXF(), rRec
.GetItemSet(), rRec
.GetScNumFmt(), rRec
.GetXclFont() };
2788 sal_uInt32
XclExpXFBuffer::InsertCellXF( const ScPatternAttr
* pPattern
, sal_Int16 nScript
,
2789 sal_uInt32 nForceScNumFmt
, sal_uInt16 nForceXclFont
, bool bForceLineBreak
)
2791 const ScPatternAttr
* pDefPattern
= GetDoc().GetDefPattern();
2793 pPattern
= pDefPattern
;
2795 // special handling for default cell formatting
2796 if( (pPattern
== pDefPattern
) && !bForceLineBreak
&&
2797 (nForceScNumFmt
== NUMBERFORMAT_ENTRY_NOT_FOUND
) &&
2798 (nForceXclFont
== EXC_FONT_NOTFOUND
) )
2800 // Is it the first try to insert the default cell format?
2801 bool& rbPredefined
= maBuiltInMap
[ EXC_XF_DEFAULTCELL
].mbPredefined
;
2804 // remove old entry in find-map
2805 auto & rPositions
= maXFFindMap
[ToFindKey(*maXFList
.GetRecord(EXC_XF_DEFAULTCELL
))];
2806 auto it
= std::find(rPositions
.begin(), rPositions
.end(), EXC_XF_DEFAULTCELL
);
2807 rPositions
.erase(it
);
2808 // replace default cell pattern
2809 XclExpXFRef xNewXF
= new XclExpXF( GetRoot(), *pPattern
, nScript
);
2810 maXFList
.ReplaceRecord( xNewXF
, EXC_XF_DEFAULTCELL
);
2811 // and add new entry in find-map
2812 maXFFindMap
[ToFindKey(*xNewXF
)].push_back(EXC_XF_DEFAULTCELL
);
2813 rbPredefined
= false;
2815 return GetDefCellXFId();
2818 sal_uInt32 nXFId
= FindXF( *pPattern
, nForceScNumFmt
, nForceXclFont
, bForceLineBreak
);
2819 if( nXFId
== EXC_XFID_NOTFOUND
)
2821 // not found - insert new cell XF
2822 if( maXFList
.GetSize() < EXC_XFLIST_HARDLIMIT
)
2824 auto pNewExp
= new XclExpXF(
2825 GetRoot(), *pPattern
, nScript
, nForceScNumFmt
, nForceXclFont
, bForceLineBreak
);
2826 maXFList
.AppendNewRecord( pNewExp
);
2827 // do not set nXFId before the AppendNewRecord() call - it may insert 2 XFs (style+cell)
2828 nXFId
= static_cast< sal_uInt32
>( maXFList
.GetSize() - 1 );
2829 maXFFindMap
[ToFindKey(*pNewExp
)].push_back(nXFId
);
2833 // list full - fall back to default cell XF
2834 nXFId
= GetDefCellXFId();
2840 sal_uInt32
XclExpXFBuffer::InsertStyleXF( const SfxStyleSheetBase
& rStyleSheet
)
2842 // *** try, if it is a built-in style - create new XF or replace existing predefined XF ***
2844 sal_uInt8 nStyleId
, nLevel
;
2845 if( XclTools::GetBuiltInStyleId( nStyleId
, nLevel
, rStyleSheet
.GetName() ) )
2847 // try to find the built-in XF record (if already created in InsertDefaultRecords())
2848 sal_uInt32 nXFId
= FindBuiltInXF( nStyleId
, nLevel
);
2849 if( nXFId
== EXC_XFID_NOTFOUND
)
2851 // built-in style XF not yet created - do it now
2852 XclExpXFRef xXF
= new XclExpXF( GetRoot(), rStyleSheet
);
2853 nXFId
= AppendBuiltInXFWithStyle( xXF
, nStyleId
, nLevel
);
2854 // this new XF record is not predefined
2855 maBuiltInMap
[ nXFId
].mbPredefined
= false;
2859 OSL_ENSURE( maXFList
.HasRecord( nXFId
), "XclExpXFBuffer::InsertStyleXF - built-in XF not found" );
2860 // XF record still predefined? -> Replace with real XF
2861 bool& rbPredefined
= maBuiltInMap
[ nXFId
].mbPredefined
;
2864 // remove old entry in find-map
2865 auto & rPositions
= maXFFindMap
[ToFindKey(*maXFList
.GetRecord(nXFId
))];
2866 auto it
= std::find(rPositions
.begin(), rPositions
.end(), nXFId
);
2867 rPositions
.erase(it
);
2868 // replace predefined built-in style (ReplaceRecord() deletes old record)
2869 XclExpXFRef pNewExp
= new XclExpXF( GetRoot(), rStyleSheet
);
2870 maXFList
.ReplaceRecord( pNewExp
, nXFId
);
2871 // and add new entry in find-map
2872 maXFFindMap
[ToFindKey(*pNewExp
)].push_back(nXFId
);
2873 rbPredefined
= false;
2877 // STYLE already inserted? (may be not, i.e. for RowLevel/ColLevel or Hyperlink styles)
2878 bool& rbHasStyleRec
= maBuiltInMap
[ nXFId
].mbHasStyleRec
;
2879 if( !rbHasStyleRec
)
2881 maStyleList
.AppendNewRecord( new XclExpStyle( nXFId
, nStyleId
, nLevel
) );
2882 rbHasStyleRec
= true;
2888 // *** try to find the XF record of a user-defined style ***
2890 sal_uInt32 nXFId
= FindXF( rStyleSheet
);
2891 if( nXFId
== EXC_XFID_NOTFOUND
)
2893 // not found - insert new style XF and STYLE
2894 nXFId
= static_cast< sal_uInt32
>( maXFList
.GetSize() );
2895 if( nXFId
< EXC_XFLIST_HARDLIMIT
)
2897 auto pNewExp
= new XclExpXF( GetRoot(), rStyleSheet
);
2898 maXFList
.AppendNewRecord( pNewExp
);
2899 // create the STYLE record
2900 if( !rStyleSheet
.GetName().isEmpty() )
2901 maStyleList
.AppendNewRecord( new XclExpStyle( nXFId
, rStyleSheet
.GetName() ) );
2902 maXFFindMap
[ToFindKey(*pNewExp
)].push_back(nXFId
);
2905 // list full - fall back to default style XF
2906 nXFId
= GetXFIdFromIndex( EXC_XF_DEFAULTSTYLE
);
2911 void XclExpXFBuffer::InsertUserStyles()
2913 SfxStyleSheetIterator
aStyleIter( GetDoc().GetStyleSheetPool(), SfxStyleFamily::Para
);
2914 for( SfxStyleSheetBase
* pStyleSheet
= aStyleIter
.First(); pStyleSheet
; pStyleSheet
= aStyleIter
.Next() )
2915 if( pStyleSheet
->IsUserDefined() && !lclIsBuiltInStyle( pStyleSheet
->GetName() ) )
2916 InsertStyleXF( *pStyleSheet
);
2919 sal_uInt32
XclExpXFBuffer::AppendBuiltInXF( XclExpXFRef
const & xXF
, sal_uInt8 nStyleId
, sal_uInt8 nLevel
)
2921 sal_uInt32 nXFId
= static_cast< sal_uInt32
>( maXFList
.GetSize() );
2922 maXFList
.AppendRecord( xXF
);
2923 maXFFindMap
[ToFindKey(*xXF
)].push_back(nXFId
);
2924 XclExpBuiltInInfo
& rInfo
= maBuiltInMap
[ nXFId
];
2925 rInfo
.mnStyleId
= nStyleId
;
2926 rInfo
.mnLevel
= nLevel
;
2927 rInfo
.mbPredefined
= true;
2931 sal_uInt32
XclExpXFBuffer::AppendBuiltInXFWithStyle( XclExpXFRef
const & xXF
, sal_uInt8 nStyleId
, sal_uInt8 nLevel
)
2933 sal_uInt32 nXFId
= AppendBuiltInXF( xXF
, nStyleId
, nLevel
);
2934 maStyleList
.AppendNewRecord( new XclExpStyle( nXFId
, nStyleId
, nLevel
) );
2935 maBuiltInMap
[ nXFId
].mbHasStyleRec
= true; // mark existing STYLE record
2939 static XclExpCellArea
lcl_GetPatternFill_None()
2941 XclExpCellArea aFill
;
2942 aFill
.mnPattern
= EXC_PATT_NONE
;
2946 static XclExpCellArea
lcl_GetPatternFill_Gray125()
2948 XclExpCellArea aFill
;
2949 aFill
.mnPattern
= EXC_PATT_12_5_PERC
;
2950 aFill
.mnForeColor
= 0;
2951 aFill
.mnBackColor
= 0;
2955 void XclExpXFBuffer::InsertDefaultRecords()
2957 maFills
.push_back( lcl_GetPatternFill_None() );
2958 maFills
.push_back( lcl_GetPatternFill_Gray125() );
2960 // index 0: default style
2961 if( SfxStyleSheetBase
* pDefStyleSheet
= GetStyleSheetPool().Find( ScResId( STR_STYLENAME_STANDARD
), SfxStyleFamily::Para
) )
2963 XclExpXFRef xDefStyle
= new XclExpXF( GetRoot(), *pDefStyleSheet
);
2964 sal_uInt32 nXFId
= AppendBuiltInXFWithStyle( xDefStyle
, EXC_STYLE_NORMAL
);
2965 // mark this XF as not predefined, prevents overwriting
2966 maBuiltInMap
[ nXFId
].mbPredefined
= false;
2970 OSL_FAIL( "XclExpXFBuffer::InsertDefaultRecords - default style not found" );
2971 XclExpXFRef xDefStyle
= new XclExpDefaultXF( GetRoot(), false );
2972 xDefStyle
->SetAllUsedFlags( true );
2973 AppendBuiltInXFWithStyle( xDefStyle
, EXC_STYLE_NORMAL
);
2976 // index 1-14: RowLevel and ColLevel styles (without STYLE records)
2977 XclExpDefaultXF
aLevelStyle( GetRoot(), false );
2978 // RowLevel_1, ColLevel_1
2979 aLevelStyle
.SetFont( 1 );
2980 AppendBuiltInXF( new XclExpDefaultXF( aLevelStyle
), EXC_STYLE_ROWLEVEL
, 0 );
2981 AppendBuiltInXF( new XclExpDefaultXF( aLevelStyle
), EXC_STYLE_COLLEVEL
, 0 );
2982 // RowLevel_2, ColLevel_2
2983 aLevelStyle
.SetFont( 2 );
2984 AppendBuiltInXF( new XclExpDefaultXF( aLevelStyle
), EXC_STYLE_ROWLEVEL
, 1 );
2985 AppendBuiltInXF( new XclExpDefaultXF( aLevelStyle
), EXC_STYLE_COLLEVEL
, 1 );
2986 // RowLevel_3, ColLevel_3 ... RowLevel_7, ColLevel_7
2987 aLevelStyle
.SetFont( 0 );
2988 for( sal_uInt8 nLevel
= 2; nLevel
< EXC_STYLE_LEVELCOUNT
; ++nLevel
)
2990 AppendBuiltInXF( new XclExpDefaultXF( aLevelStyle
), EXC_STYLE_ROWLEVEL
, nLevel
);
2991 AppendBuiltInXF( new XclExpDefaultXF( aLevelStyle
), EXC_STYLE_COLLEVEL
, nLevel
);
2994 // index 15: default hard cell format, placeholder to be able to add more built-in styles
2995 maXFList
.AppendNewRecord( new XclExpDefaultXF( GetRoot(), true ) );
2996 maXFFindMap
[ToFindKey(*maXFList
.GetRecord(maXFList
.GetSize()-1))].push_back(maXFList
.GetSize()-1);
2997 maBuiltInMap
[ EXC_XF_DEFAULTCELL
].mbPredefined
= true;
2999 // index 16-20: other built-in styles
3000 XclExpDefaultXF
aFormatStyle( GetRoot(), false );
3001 aFormatStyle
.SetFont( 1 );
3002 aFormatStyle
.SetNumFmt( 43 );
3003 AppendBuiltInXFWithStyle( new XclExpDefaultXF( aFormatStyle
), EXC_STYLE_COMMA
);
3004 aFormatStyle
.SetNumFmt( 41 );
3005 AppendBuiltInXFWithStyle( new XclExpDefaultXF( aFormatStyle
), EXC_STYLE_COMMA_0
);
3006 aFormatStyle
.SetNumFmt( 44 );
3007 AppendBuiltInXFWithStyle( new XclExpDefaultXF( aFormatStyle
), EXC_STYLE_CURRENCY
);
3008 aFormatStyle
.SetNumFmt( 42 );
3009 AppendBuiltInXFWithStyle( new XclExpDefaultXF( aFormatStyle
), EXC_STYLE_CURRENCY_0
);
3010 aFormatStyle
.SetNumFmt( 9 );
3011 AppendBuiltInXFWithStyle( new XclExpDefaultXF( aFormatStyle
), EXC_STYLE_PERCENT
);
3013 // other built-in style XF records (i.e. Hyperlink styles) are created on demand
3015 /* Insert the real default hard cell format -> 0 is document default pattern.
3016 Do it here (and not already above) to really have all built-in styles. */
3017 Insert( nullptr, GetDefApiScript() );
3020 void XclExpXFBuffer::AppendXFIndex( sal_uInt32 nXFId
)
3022 OSL_ENSURE( nXFId
< maXFIndexVec
.size(), "XclExpXFBuffer::AppendXFIndex - XF ID out of range" );
3023 maXFIndexVec
[ nXFId
] = static_cast< sal_uInt16
>( maSortedXFList
.GetSize() );
3024 XclExpXFRef xXF
= maXFList
.GetRecord( nXFId
);
3025 AddBorderAndFill( *xXF
);
3026 maSortedXFList
.AppendRecord( xXF
);
3027 OSL_ENSURE( maXFList
.HasRecord( nXFId
), "XclExpXFBuffer::AppendXFIndex - XF not found" );
3030 void XclExpXFBuffer::AddBorderAndFill( const XclExpXF
& rXF
)
3032 if( std::none_of( maBorders
.begin(), maBorders
.end(), XclExpBorderPred( rXF
.GetBorderData() ) ) )
3034 maBorders
.push_back( rXF
.GetBorderData() );
3037 if( std::none_of( maFills
.begin(), maFills
.end(), XclExpFillPred( rXF
.GetAreaData() ) ) )
3039 maFills
.push_back( rXF
.GetAreaData() );
3043 XclExpDxfs::XclExpDxfs( const XclExpRoot
& rRoot
)
3044 : XclExpRoot( rRoot
),
3045 mpKeywordTable( new NfKeywordTable
)
3047 // Special number formatter for conversion.
3048 SvNumberFormatterPtr
xFormatter(new SvNumberFormatter( comphelper::getProcessComponentContext(), LANGUAGE_ENGLISH_US
));
3049 xFormatter
->FillKeywordTableForExcel( *mpKeywordTable
);
3051 SCTAB nTables
= rRoot
.GetDoc().GetTableCount();
3052 sal_Int32 nDxfId
= 0;
3053 for(SCTAB nTab
= 0; nTab
< nTables
; ++nTab
)
3056 std::vector
<ScDBData
*> pDBData
= rRoot
.GetDoc().GetDBCollection()->GetAllDBsFromTab(nTab
);
3057 for (auto& pData
: pDBData
)
3060 pData
->GetArea(aRange
);
3061 for (auto nCol
= aRange
.aStart
.Col(); nCol
<= aRange
.aEnd
.Col(); nCol
++)
3063 ScFilterEntries aFilterEntries
;
3064 rRoot
.GetDoc().GetFilterEntriesArea(nCol
, aRange
.aStart
.Row(),
3065 aRange
.aEnd
.Row(), nTab
, true, aFilterEntries
);
3067 // Excel has all filter values stored as foreground colors
3068 // Does not matter it is text color or cell background color
3069 for (auto& rColor
: aFilterEntries
.getBackgroundColors())
3071 if (!maColorToDxfId
.emplace(rColor
, nDxfId
).second
)
3074 std::unique_ptr
<XclExpCellArea
> pExpCellArea(new XclExpCellArea(rColor
, 0));
3075 maDxf
.push_back(std::make_unique
<XclExpDxf
>(rRoot
, std::move(pExpCellArea
)));
3078 for (auto& rColor
: aFilterEntries
.getTextColors())
3080 if (!maColorToDxfId
.emplace(rColor
, nDxfId
).second
)
3083 std::unique_ptr
<XclExpCellArea
> pExpCellArea(new XclExpCellArea(rColor
, 0));
3084 maDxf
.push_back(std::make_unique
<XclExpDxf
>(rRoot
, std::move(pExpCellArea
)));
3090 // Conditional formatting
3091 ScConditionalFormatList
* pList
= rRoot
.GetDoc().GetCondFormList(nTab
);
3094 for (const auto& rxItem
: *pList
)
3096 size_t nEntryCount
= rxItem
->size();
3097 for (size_t nFormatEntry
= 0; nFormatEntry
< nEntryCount
; ++nFormatEntry
)
3099 const ScFormatEntry
* pFormatEntry
= rxItem
->GetEntry(nFormatEntry
);
3101 || (pFormatEntry
->GetType() != ScFormatEntry::Type::Condition
3102 && pFormatEntry
->GetType() != ScFormatEntry::Type::Date
3103 && pFormatEntry
->GetType() != ScFormatEntry::Type::ExtCondition
))
3106 OUString aStyleName
;
3107 if (pFormatEntry
->GetType() == ScFormatEntry::Type::Condition
3108 || pFormatEntry
->GetType() == ScFormatEntry::Type::ExtCondition
)
3110 const ScCondFormatEntry
* pEntry
= static_cast<const ScCondFormatEntry
*>(pFormatEntry
);
3111 aStyleName
= pEntry
->GetStyle();
3115 const ScCondDateFormatEntry
* pEntry
= static_cast<const ScCondDateFormatEntry
*>(pFormatEntry
);
3116 aStyleName
= pEntry
->GetStyleName();
3119 if (maStyleNameToDxfId
.emplace(aStyleName
, nDxfId
).second
)
3121 SfxStyleSheetBase
* pStyle
= rRoot
.GetDoc().GetStyleSheetPool()->Find(aStyleName
, SfxStyleFamily::Para
);
3125 SfxItemSet
& rSet
= pStyle
->GetItemSet();
3127 std::unique_ptr
<XclExpCellBorder
> pBorder(new XclExpCellBorder
);
3128 if (!pBorder
->FillFromItemSet( rSet
, GetPalette(), GetBiff()) )
3133 std::unique_ptr
<XclExpCellAlign
> pAlign(new XclExpCellAlign
);
3134 if (!pAlign
->FillFromItemSet(rRoot
, rSet
, false, GetBiff()))
3139 std::unique_ptr
<XclExpCellProt
> pCellProt(new XclExpCellProt
);
3140 if (!pCellProt
->FillFromItemSet( rSet
))
3145 std::unique_ptr
<XclExpColor
> pColor(new XclExpColor
);
3146 if(!pColor
->FillFromItemSet( rSet
))
3151 std::unique_ptr
<XclExpDxfFont
> pFont(new XclExpDxfFont(rRoot
, rSet
));
3153 std::unique_ptr
<XclExpNumFmt
> pNumFormat
;
3154 const SfxPoolItem
*pPoolItem
= nullptr;
3155 if( rSet
.GetItemState( ATTR_VALUE_FORMAT
, true, &pPoolItem
) == SfxItemState::SET
)
3157 sal_uInt32 nScNumFmt
= static_cast< const SfxUInt32Item
* >(pPoolItem
)->GetValue();
3158 sal_Int32 nXclNumFmt
= GetRoot().GetNumFmtBuffer().Insert(nScNumFmt
);
3159 pNumFormat
.reset(new XclExpNumFmt( nScNumFmt
, nXclNumFmt
, GetNumberFormatCode( *this, nScNumFmt
, xFormatter
.get(), mpKeywordTable
.get() )));
3162 maDxf
.push_back(std::make_unique
<XclExpDxf
>( rRoot
, std::move(pAlign
), std::move(pBorder
),
3163 std::move(pFont
), std::move(pNumFormat
), std::move(pCellProt
), std::move(pColor
) ));
3173 sal_Int32
XclExpDxfs::GetDxfId( const OUString
& rStyleName
) const
3175 std::map
<OUString
, sal_Int32
>::const_iterator itr
= maStyleNameToDxfId
.find(rStyleName
);
3176 if(itr
!= maStyleNameToDxfId
.end())
3181 sal_Int32
XclExpDxfs::GetDxfByColor(Color aColor
) const
3183 std::map
<Color
, sal_Int32
>::const_iterator itr
= maColorToDxfId
.find(aColor
);
3184 if (itr
!= maColorToDxfId
.end())
3189 void XclExpDxfs::AddColor(Color aColor
)
3191 maColorToDxfId
.emplace(aColor
, maDxf
.size());
3193 std::unique_ptr
<XclExpCellArea
> pExpCellArea(new XclExpCellArea(aColor
, 0));
3194 maDxf
.push_back(std::make_unique
<XclExpDxf
>(GetRoot(), std::move(pExpCellArea
)));
3197 void XclExpDxfs::SaveXml( XclExpXmlStream
& rStrm
)
3202 sax_fastparser::FSHelperPtr
& rStyleSheet
= rStrm
.GetCurrentStream();
3203 rStyleSheet
->startElement(XML_dxfs
, XML_count
, OString::number(maDxf
.size()));
3205 for ( auto& rxDxf
: maDxf
)
3207 rxDxf
->SaveXml( rStrm
);
3210 rStyleSheet
->endElement( XML_dxfs
);
3213 XclExpDxf::XclExpDxf( const XclExpRoot
& rRoot
, std::unique_ptr
<XclExpCellAlign
> pAlign
, std::unique_ptr
<XclExpCellBorder
> pBorder
,
3214 std::unique_ptr
<XclExpDxfFont
> pFont
, std::unique_ptr
<XclExpNumFmt
> pNumberFmt
, std::unique_ptr
<XclExpCellProt
> pProt
,
3215 std::unique_ptr
<XclExpColor
> pColor
)
3216 : XclExpRoot( rRoot
),
3217 mpAlign(std::move(pAlign
)),
3218 mpBorder(std::move(pBorder
)),
3219 mpFont(std::move(pFont
)),
3220 mpNumberFmt(std::move(pNumberFmt
)),
3221 mpProt(std::move(pProt
)),
3222 mpColor(std::move(pColor
))
3226 XclExpDxf::XclExpDxf(const XclExpRoot
& rRoot
, std::unique_ptr
<XclExpCellArea
> pCellArea
)
3228 , mpCellArea(std::move(pCellArea
))
3232 XclExpDxf::~XclExpDxf()
3236 void XclExpDxf::SaveXml( XclExpXmlStream
& rStrm
)
3238 sax_fastparser::FSHelperPtr
& rStyleSheet
= rStrm
.GetCurrentStream();
3239 rStyleSheet
->startElement(XML_dxf
);
3242 mpFont
->SaveXml(rStrm
);
3244 mpNumberFmt
->SaveXml(rStrm
);
3246 mpColor
->SaveXml(rStrm
);
3248 mpAlign
->SaveXml(rStrm
);
3250 mpBorder
->SaveXml(rStrm
);
3252 mpProt
->SaveXml(rStrm
);
3254 mpCellArea
->SaveXml(rStrm
);
3255 rStyleSheet
->endElement( XML_dxf
);
3258 void XclExpDxf::SaveXmlExt( XclExpXmlStream
& rStrm
)
3260 sax_fastparser::FSHelperPtr
& rStyleSheet
= rStrm
.GetCurrentStream();
3261 rStyleSheet
->startElementNS( XML_x14
, XML_dxf
);
3264 mpFont
->SaveXml(rStrm
);
3266 mpNumberFmt
->SaveXml(rStrm
);
3268 mpColor
->SaveXml(rStrm
);
3270 mpAlign
->SaveXml(rStrm
);
3272 mpBorder
->SaveXml(rStrm
);
3274 mpProt
->SaveXml(rStrm
);
3275 rStyleSheet
->endElementNS( XML_x14
, XML_dxf
);
3279 XclExpXmlStyleSheet::XclExpXmlStyleSheet( const XclExpRoot
& rRoot
)
3280 : XclExpRoot( rRoot
)
3284 void XclExpXmlStyleSheet::SaveXml( XclExpXmlStream
& rStrm
)
3286 sax_fastparser::FSHelperPtr aStyleSheet
= rStrm
.CreateOutputStream(
3289 rStrm
.GetCurrentStream()->getOutputStream(),
3290 "application/vnd.openxmlformats-officedocument.spreadsheetml.styles+xml",
3291 oox::getRelationship(Relationship::STYLES
));
3292 rStrm
.PushStream( aStyleSheet
);
3294 aStyleSheet
->startElement(XML_styleSheet
, XML_xmlns
, rStrm
.getNamespaceURL(OOX_NS(xls
)));
3296 CreateRecord( EXC_ID_FORMATLIST
)->SaveXml( rStrm
);
3297 CreateRecord( EXC_ID_FONTLIST
)->SaveXml( rStrm
);
3298 CreateRecord( EXC_ID_XFLIST
)->SaveXml( rStrm
);
3299 CreateRecord( EXC_ID_DXFS
)->SaveXml( rStrm
);
3300 CreateRecord( EXC_ID_PALETTE
)->SaveXml( rStrm
);
3302 aStyleSheet
->endElement( XML_styleSheet
);
3307 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */