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