Version 6.4.0.3, tag libreoffice-6.4.0.3
[LibreOffice.git] / sc / source / filter / oox / stylesbuffer.cxx
bloba6887b7bd10373baed9eadf8563c1ba960d26277
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #include <stylesbuffer.hxx>
22 #include <com/sun/star/awt/FontDescriptor.hpp>
23 #include <com/sun/star/awt/FontFamily.hpp>
24 #include <com/sun/star/awt/FontPitch.hpp>
25 #include <com/sun/star/awt/FontSlant.hpp>
26 #include <com/sun/star/awt/FontStrikeout.hpp>
27 #include <com/sun/star/awt/FontType.hpp>
28 #include <com/sun/star/awt/FontWeight.hpp>
29 #include <com/sun/star/awt/FontUnderline.hpp>
30 #include <com/sun/star/awt/XDevice.hpp>
31 #include <com/sun/star/awt/XFont2.hpp>
32 #include <com/sun/star/container/XIndexAccess.hpp>
33 #include <com/sun/star/style/XStyle.hpp>
34 #include <com/sun/star/text/WritingMode2.hpp>
35 #include <com/sun/star/table/BorderLineStyle.hpp>
36 #include <com/sun/star/table/CellVertJustify2.hpp>
37 #include <com/sun/star/table/CellJustifyMethod.hpp>
38 #include <editeng/justifyitem.hxx>
39 #include <editeng/frmdiritem.hxx>
40 #include <editeng/fontitem.hxx>
41 #include <editeng/postitem.hxx>
42 #include <editeng/fhgtitem.hxx>
43 #include <editeng/wghtitem.hxx>
44 #include <editeng/udlnitem.hxx>
45 #include <editeng/colritem.hxx>
46 #include <editeng/crossedoutitem.hxx>
47 #include <editeng/contouritem.hxx>
48 #include <editeng/escapementitem.hxx>
49 #include <editeng/shdditem.hxx>
50 #include <editeng/eeitem.hxx>
51 #include <editeng/borderline.hxx>
52 #include <editeng/boxitem.hxx>
53 #include <editeng/lineitem.hxx>
54 #include <editeng/brushitem.hxx>
55 #include <svx/rotmodit.hxx>
56 #include <tools/fontenum.hxx>
57 #include <vcl/unohelp.hxx>
58 #include <rtl/tencinfo.h>
59 #include <rtl/ustrbuf.hxx>
60 #include <sal/log.hxx>
61 #include <osl/diagnose.h>
62 #include <oox/core/filterbase.hxx>
63 #include <oox/helper/attributelist.hxx>
64 #include <oox/helper/binaryinputstream.hxx>
65 #include <oox/helper/containerhelper.hxx>
66 #include <oox/helper/propertymap.hxx>
67 #include <oox/helper/propertyset.hxx>
68 #include <oox/token/namespaces.hxx>
69 #include <oox/token/properties.hxx>
70 #include <oox/token/tokens.hxx>
71 #include <themebuffer.hxx>
72 #include <unitconverter.hxx>
73 #include <document.hxx>
74 #include <stlpool.hxx>
75 #include <docpool.hxx>
76 #include <ftools.hxx>
77 #include <scitems.hxx>
78 #include <attrib.hxx>
79 #include <globstr.hrc>
80 #include <scresid.hxx>
81 #include <xlconst.hxx>
82 #include <documentimport.hxx>
83 #include <numformat.hxx>
84 #include <patattr.hxx>
85 #include <stlsheet.hxx>
86 #include <biffhelper.hxx>
88 namespace oox {
89 namespace xls {
91 using namespace ::com::sun::star::awt;
92 using namespace ::com::sun::star::container;
93 using namespace ::com::sun::star::style;
94 using namespace ::com::sun::star::table;
95 using namespace ::com::sun::star::text;
96 using namespace ::com::sun::star::uno;
99 namespace {
101 // OOXML constants ------------------------------------------------------------
103 // OOXML predefined color indexes (also used in BIFF3-BIFF8)
104 const sal_Int32 OOX_COLOR_USEROFFSET = 0; /// First user defined color in palette (OOXML/BIFF12).
106 // OOXML font family (also used in BIFF)
107 const sal_Int32 OOX_FONTFAMILY_NONE = 0;
108 const sal_Int32 OOX_FONTFAMILY_ROMAN = 1;
109 const sal_Int32 OOX_FONTFAMILY_SWISS = 2;
110 const sal_Int32 OOX_FONTFAMILY_MODERN = 3;
111 const sal_Int32 OOX_FONTFAMILY_SCRIPT = 4;
112 const sal_Int32 OOX_FONTFAMILY_DECORATIVE = 5;
114 // OOXML cell text direction (also used in BIFF)
115 const sal_Int32 OOX_XF_TEXTDIR_CONTEXT = 0;
116 const sal_Int32 OOX_XF_TEXTDIR_LTR = 1;
117 const sal_Int32 OOX_XF_TEXTDIR_RTL = 2;
119 // OOXML cell rotation (also used in BIFF)
120 const sal_Int32 OOX_XF_ROTATION_NONE = 0;
121 const sal_Int32 OOX_XF_ROTATION_STACKED = 255;
123 // OOXML cell indentation
124 const sal_Int32 OOX_XF_INDENT_NONE = 0;
126 // OOXML built-in cell styles (also used in BIFF)
127 const sal_Int32 OOX_STYLE_NORMAL = 0; /// Default cell style.
128 const sal_Int32 OOX_STYLE_ROWLEVEL = 1; /// RowLevel_x cell style.
129 const sal_Int32 OOX_STYLE_COLLEVEL = 2; /// ColLevel_x cell style.
131 // BIFF12 constants -----------------------------------------------------------
133 // BIFF12 color types
134 const sal_uInt8 BIFF12_COLOR_AUTO = 0;
135 const sal_uInt8 BIFF12_COLOR_INDEXED = 1;
136 const sal_uInt8 BIFF12_COLOR_RGB = 2;
137 const sal_uInt8 BIFF12_COLOR_THEME = 3;
139 // BIFF12 diagonal borders
140 const sal_uInt8 BIFF12_BORDER_DIAG_TLBR = 0x01; /// Top-left to bottom-right.
141 const sal_uInt8 BIFF12_BORDER_DIAG_BLTR = 0x02; /// Bottom-left to top-right.
143 // BIFF12 gradient fill
144 const sal_Int32 BIFF12_FILL_GRADIENT = 40;
146 // BIFF12 XF flags
147 const sal_uInt32 BIFF12_XF_WRAPTEXT = 0x00400000;
148 const sal_uInt32 BIFF12_XF_JUSTLASTLINE = 0x00800000;
149 const sal_uInt32 BIFF12_XF_SHRINK = 0x01000000;
150 const sal_uInt32 BIFF12_XF_LOCKED = 0x10000000;
151 const sal_uInt32 BIFF12_XF_HIDDEN = 0x20000000;
153 // BIFF12 XF attribute used flags
154 const sal_uInt16 BIFF12_XF_NUMFMT_USED = 0x0001;
155 const sal_uInt16 BIFF12_XF_FONT_USED = 0x0002;
156 const sal_uInt16 BIFF12_XF_ALIGN_USED = 0x0004;
157 const sal_uInt16 BIFF12_XF_BORDER_USED = 0x0008;
158 const sal_uInt16 BIFF12_XF_AREA_USED = 0x0010;
159 const sal_uInt16 BIFF12_XF_PROT_USED = 0x0020;
161 // BIFF12 DXF constants
162 const sal_uInt16 BIFF12_DXF_FILL_PATTERN = 0;
163 const sal_uInt16 BIFF12_DXF_FILL_FGCOLOR = 1;
164 const sal_uInt16 BIFF12_DXF_FILL_BGCOLOR = 2;
165 const sal_uInt16 BIFF12_DXF_FILL_GRADIENT = 3;
166 const sal_uInt16 BIFF12_DXF_FILL_STOP = 4;
167 const sal_uInt16 BIFF12_DXF_FONT_COLOR = 5;
168 const sal_uInt16 BIFF12_DXF_BORDER_TOP = 6;
169 const sal_uInt16 BIFF12_DXF_BORDER_BOTTOM = 7;
170 const sal_uInt16 BIFF12_DXF_BORDER_LEFT = 8;
171 const sal_uInt16 BIFF12_DXF_BORDER_RIGHT = 9;
172 const sal_uInt16 BIFF12_DXF_FONT_NAME = 24;
173 const sal_uInt16 BIFF12_DXF_FONT_WEIGHT = 25;
174 const sal_uInt16 BIFF12_DXF_FONT_UNDERLINE = 26;
175 const sal_uInt16 BIFF12_DXF_FONT_ESCAPEMENT = 27;
176 const sal_uInt16 BIFF12_DXF_FONT_ITALIC = 28;
177 const sal_uInt16 BIFF12_DXF_FONT_STRIKE = 29;
178 const sal_uInt16 BIFF12_DXF_FONT_OUTLINE = 30;
179 const sal_uInt16 BIFF12_DXF_FONT_SHADOW = 31;
180 const sal_uInt16 BIFF12_DXF_FONT_HEIGHT = 36;
181 const sal_uInt16 BIFF12_DXF_FONT_SCHEME = 37;
182 const sal_uInt16 BIFF12_DXF_NUMFMT_CODE = 38;
183 const sal_uInt16 BIFF12_DXF_NUMFMT_ID = 41;
185 // BIFF12 CELLSTYLE flags
186 const sal_uInt16 BIFF12_CELLSTYLE_BUILTIN = 0x0001;
187 const sal_uInt16 BIFF12_CELLSTYLE_HIDDEN = 0x0002;
188 const sal_uInt16 BIFF12_CELLSTYLE_CUSTOM = 0x0004;
190 // BIFF constants -------------------------------------------------------------
192 // BIFF font flags, also used in BIFF12
193 const sal_uInt16 BIFF_FONTFLAG_ITALIC = 0x0002;
194 const sal_uInt16 BIFF_FONTFLAG_STRIKEOUT = 0x0008;
195 const sal_uInt16 BIFF_FONTFLAG_OUTLINE = 0x0010;
196 const sal_uInt16 BIFF_FONTFLAG_SHADOW = 0x0020;
198 // BIFF font weight
199 const sal_uInt16 BIFF_FONTWEIGHT_BOLD = 450;
201 // BIFF font underline, also used in BIFF12
202 const sal_uInt8 BIFF_FONTUNDERL_NONE = 0;
203 const sal_uInt8 BIFF_FONTUNDERL_SINGLE = 1;
204 const sal_uInt8 BIFF_FONTUNDERL_DOUBLE = 2;
205 const sal_uInt8 BIFF_FONTUNDERL_SINGLE_ACC = 33;
206 const sal_uInt8 BIFF_FONTUNDERL_DOUBLE_ACC = 34;
208 ::Color lclReadRgbColor( BinaryInputStream& rStrm )
210 sal_uInt8 nR, nG, nB, nA;
211 nR = rStrm.readuChar();
212 nG = rStrm.readuChar();
213 nB = rStrm.readuChar();
214 nA = rStrm.readuChar();
215 sal_Int32 nValue = nA;
216 nValue <<= 8;
217 nValue |= nR;
218 nValue <<= 8;
219 nValue |= nG;
220 nValue <<= 8;
221 nValue |= nB;
222 return ::Color(nValue);
225 } // namespace
227 ExcelGraphicHelper::ExcelGraphicHelper( const WorkbookHelper& rHelper ) :
228 GraphicHelper( rHelper.getBaseFilter().getComponentContext(), rHelper.getBaseFilter().getTargetFrame(), rHelper.getBaseFilter().getStorage() ),
229 WorkbookHelper( rHelper )
233 ::Color ExcelGraphicHelper::getSchemeColor( sal_Int32 nToken ) const
235 return getTheme().getColorByToken( nToken );
238 ::Color ExcelGraphicHelper::getPaletteColor( sal_Int32 nPaletteIdx ) const
240 return getStyles().getPaletteColor( nPaletteIdx );
243 void Color::setAuto()
245 clearTransformations();
246 setSchemeClr( XML_phClr );
249 void Color::setRgb( ::Color nRgbValue, double fTint )
251 clearTransformations();
252 setSrgbClr( sal_uInt32(nRgbValue) & 0xFFFFFF );
253 if( fTint != 0.0 ) addExcelTintTransformation( fTint );
256 void Color::setTheme( sal_Int32 nThemeIdx, double fTint )
258 clearTransformations();
259 static const sal_Int32 spnColorTokens[] = {
260 XML_lt1, XML_dk1, XML_lt2, XML_dk2, XML_accent1, XML_accent2,
261 XML_accent3, XML_accent4, XML_accent5, XML_accent6, XML_hlink, XML_folHlink };
262 setSchemeClr( STATIC_ARRAY_SELECT( spnColorTokens, nThemeIdx, XML_TOKEN_INVALID ) );
263 if( fTint != 0.0 ) addExcelTintTransformation( fTint );
266 void Color::setIndexed( sal_Int32 nPaletteIdx, double fTint )
268 clearTransformations();
269 setPaletteClr( nPaletteIdx );
270 if( fTint != 0.0 ) addExcelTintTransformation( fTint );
273 void Color::importColor( const AttributeList& rAttribs )
275 // tdf#113271 The order of import color is very important in case of more than one color attributes was provided.
276 // This order (theme -> rgb -> indexed -> auto) is not documented and was gathered experimentally based on MS Excel 2013.
277 if( rAttribs.hasAttribute( XML_theme ) )
278 setTheme( rAttribs.getInteger( XML_theme, -1 ), rAttribs.getDouble( XML_tint, 0.0 ) );
279 else if( rAttribs.hasAttribute( XML_rgb ) )
280 setRgb( rAttribs.getIntegerHex( XML_rgb, sal_Int32(API_RGB_TRANSPARENT) ), rAttribs.getDouble( XML_tint, 0.0 ) );
281 else if( rAttribs.hasAttribute( XML_indexed ) )
282 setIndexed( rAttribs.getInteger( XML_indexed, -1 ), rAttribs.getDouble( XML_tint, 0.0 ) );
283 else if( rAttribs.getBool( XML_auto, false ) )
284 setAuto();
285 else
287 OSL_FAIL( "Color::importColor - unknown color type" );
288 setAuto();
292 void Color::importColor( SequenceInputStream& rStrm )
294 sal_uInt8 nFlags, nIndex;
295 sal_Int16 nTint;
296 nFlags = rStrm.readuChar();
297 nIndex = rStrm.readuChar();
298 nTint = rStrm.readInt16();
300 // scale tint from signed 16-bit to double range -1.0 ... 1.0
301 double fTint = nTint;
302 if( nTint < 0 )
303 fTint /= -SAL_MIN_INT16;
304 else if( nTint > 0 )
305 fTint /= SAL_MAX_INT16;
307 switch( extractValue< sal_uInt8 >( nFlags, 1, 7 ) )
309 case BIFF12_COLOR_AUTO:
310 setAuto();
311 rStrm.skip( 4 );
312 break;
313 case BIFF12_COLOR_INDEXED:
314 setIndexed( nIndex, fTint );
315 rStrm.skip( 4 );
316 break;
317 case BIFF12_COLOR_RGB:
318 setRgb( lclReadRgbColor( rStrm ), fTint );
319 break;
320 case BIFF12_COLOR_THEME:
321 setTheme( nIndex, fTint );
322 rStrm.skip( 4 );
323 break;
324 default:
325 OSL_FAIL( "Color::importColor - unknown color type" );
326 setAuto();
327 rStrm.skip( 4 );
331 void Color::importColorId( SequenceInputStream& rStrm )
333 setIndexed( rStrm.readInt32() );
336 SequenceInputStream& operator>>( SequenceInputStream& rStrm, Color& orColor )
338 orColor.importColor( rStrm );
339 return rStrm;
342 namespace {
344 /** Standard EGA colors, bright. */
345 #define PALETTE_EGA_COLORS_LIGHT \
346 ::Color(0x000000), ::Color(0xFFFFFF), ::Color(0xFF0000), ::Color(0x00FF00), ::Color(0x0000FF), ::Color(0xFFFF00), ::Color(0xFF00FF), ::Color(0x00FFFF)
347 /** Standard EGA colors), dark. */
348 #define PALETTE_EGA_COLORS_DARK \
349 ::Color(0x800000), ::Color(0x008000), ::Color(0x000080), ::Color(0x808000), ::Color(0x800080), ::Color(0x008080), ::Color(0xC0C0C0), ::Color(0x808080)
351 /** Default color table for BIFF8/BIFF12/OOXML. */
352 static const ::Color spnDefColors8[] =
354 /* 0 */ PALETTE_EGA_COLORS_LIGHT,
355 /* 8 */ PALETTE_EGA_COLORS_LIGHT,
356 /* 16 */ PALETTE_EGA_COLORS_DARK,
357 /* 24 */ ::Color(0x9999FF), ::Color(0x993366), ::Color(0xFFFFCC), ::Color(0xCCFFFF), ::Color(0x660066), ::Color(0xFF8080), ::Color(0x0066CC), ::Color(0xCCCCFF),
358 /* 32 */ ::Color(0x000080), ::Color(0xFF00FF), ::Color(0xFFFF00), ::Color(0x00FFFF), ::Color(0x800080), ::Color(0x800000), ::Color(0x008080), ::Color(0x0000FF),
359 /* 40 */ ::Color(0x00CCFF), ::Color(0xCCFFFF), ::Color(0xCCFFCC), ::Color(0xFFFF99), ::Color(0x99CCFF), ::Color(0xFF99CC), ::Color(0xCC99FF), ::Color(0xFFCC99),
360 /* 48 */ ::Color(0x3366FF), ::Color(0x33CCCC), ::Color(0x99CC00), ::Color(0xFFCC00), ::Color(0xFF9900), ::Color(0xFF6600), ::Color(0x666699), ::Color(0x969696),
361 /* 56 */ ::Color(0x003366), ::Color(0x339966), ::Color(0x003300), ::Color(0x333300), ::Color(0x993300), ::Color(0x993366), ::Color(0x333399), ::Color(0x333333)
364 #undef PALETTE_EGA_COLORS_LIGHT
365 #undef PALETTE_EGA_COLORS_DARK
367 } // namespace
369 ColorPalette::ColorPalette( const WorkbookHelper& rHelper )
370 : WorkbookHelper(rHelper)
371 , mnAppendIndex(0)
373 // default colors
374 maColors.insert( maColors.begin(), spnDefColors8, spnDefColors8 + SAL_N_ELEMENTS(spnDefColors8) );
375 mnAppendIndex = OOX_COLOR_USEROFFSET;
378 void ColorPalette::importPaletteColor( const AttributeList& rAttribs )
380 appendColor( rAttribs.getIntegerHex( XML_rgb, sal_Int32(API_RGB_WHITE) ) );
383 void ColorPalette::importPaletteColor( SequenceInputStream& rStrm )
385 ::Color nRgb = lclReadRgbColor( rStrm );
386 appendColor( nRgb );
389 ::Color ColorPalette::getColor( sal_Int32 nPaletteIdx ) const
391 ::Color nColor = API_RGB_TRANSPARENT;
392 if( const ::Color* pnPaletteColor = ContainerHelper::getVectorElement( maColors, nPaletteIdx ) )
394 nColor = *pnPaletteColor;
396 else switch( nPaletteIdx )
398 case OOX_COLOR_WINDOWTEXT3:
399 case OOX_COLOR_WINDOWTEXT:
400 case OOX_COLOR_CHWINDOWTEXT: nColor = getBaseFilter().getGraphicHelper().getSystemColor( XML_windowText ); break;
401 case OOX_COLOR_WINDOWBACK3:
402 case OOX_COLOR_WINDOWBACK:
403 case OOX_COLOR_CHWINDOWBACK: nColor = getBaseFilter().getGraphicHelper().getSystemColor( XML_window ); break;
404 case OOX_COLOR_BUTTONBACK: nColor = getBaseFilter().getGraphicHelper().getSystemColor( XML_btnFace ); break;
405 case OOX_COLOR_CHBORDERAUTO: nColor = API_RGB_BLACK; /* really always black? */ break;
406 case OOX_COLOR_NOTEBACK: nColor = getBaseFilter().getGraphicHelper().getSystemColor( XML_infoBk ); break;
407 case OOX_COLOR_NOTETEXT: nColor = getBaseFilter().getGraphicHelper().getSystemColor( XML_infoText ); break;
408 case OOX_COLOR_FONTAUTO: nColor = API_RGB_TRANSPARENT; break;
409 default: OSL_FAIL( "ColorPalette::getColor - unknown color index" );
411 return nColor;
414 void ColorPalette::appendColor( ::Color nRGBValue )
416 if( mnAppendIndex < maColors.size() )
417 maColors[ mnAppendIndex ] = nRGBValue;
418 else
419 maColors.push_back( nRGBValue );
420 ++mnAppendIndex;
423 namespace {
425 void lclSetFontName( ApiScriptFontName& rFontName, const FontDescriptor& rFontDesc, bool bHasGlyphs )
427 if( bHasGlyphs )
429 rFontName.maName = rFontDesc.Name;
430 rFontName.mnFamily = rFontDesc.Family;
431 // API font descriptor contains rtl_TextEncoding constants
432 rFontName.mnTextEnc = rFontDesc.CharSet;
434 else
436 rFontName = ApiScriptFontName();
440 } // namespace
442 FontModel::FontModel() :
443 mnScheme( XML_none ),
444 mnFamily( OOX_FONTFAMILY_NONE ),
445 mnCharSet( WINDOWS_CHARSET_DEFAULT ),
446 mfHeight( 0.0 ),
447 mnUnderline( XML_none ),
448 mnEscapement( XML_baseline ),
449 mbBold( false ),
450 mbItalic( false ),
451 mbStrikeout( false ),
452 mbOutline( false ),
453 mbShadow( false )
457 void FontModel::setBiff12Scheme( sal_uInt8 nScheme )
459 static const sal_Int32 spnSchemes[] = { XML_none, XML_major, XML_minor };
460 mnScheme = STATIC_ARRAY_SELECT( spnSchemes, nScheme, XML_none );
463 void FontModel::setBiffHeight( sal_uInt16 nHeight )
465 mfHeight = nHeight / 20.0; // convert twips to points
468 void FontModel::setBiffWeight( sal_uInt16 nWeight )
470 mbBold = nWeight >= BIFF_FONTWEIGHT_BOLD;
473 void FontModel::setBiffUnderline( sal_uInt16 nUnderline )
475 switch( nUnderline )
477 case BIFF_FONTUNDERL_NONE: mnUnderline = XML_none; break;
478 case BIFF_FONTUNDERL_SINGLE: mnUnderline = XML_single; break;
479 case BIFF_FONTUNDERL_DOUBLE: mnUnderline = XML_double; break;
480 case BIFF_FONTUNDERL_SINGLE_ACC: mnUnderline = XML_singleAccounting; break;
481 case BIFF_FONTUNDERL_DOUBLE_ACC: mnUnderline = XML_doubleAccounting; break;
482 default: mnUnderline = XML_none;
486 void FontModel::setBiffEscapement( sal_uInt16 nEscapement )
488 static const sal_Int32 spnEscapes[] = { XML_baseline, XML_superscript, XML_subscript };
489 mnEscapement = STATIC_ARRAY_SELECT( spnEscapes, nEscapement, XML_baseline );
492 ApiFontUsedFlags::ApiFontUsedFlags( bool bAllUsed ) :
493 mbNameUsed( bAllUsed ),
494 mbColorUsed( bAllUsed ),
495 mbSchemeUsed( bAllUsed ),
496 mbHeightUsed( bAllUsed ),
497 mbUnderlineUsed( bAllUsed ),
498 mbEscapementUsed( bAllUsed ),
499 mbWeightUsed( bAllUsed ),
500 mbPostureUsed( bAllUsed ),
501 mbStrikeoutUsed( bAllUsed ),
502 mbOutlineUsed( bAllUsed ),
503 mbShadowUsed( bAllUsed )
507 ApiScriptFontName::ApiScriptFontName() :
508 mnFamily( css::awt::FontFamily::DONTKNOW ),
509 mnTextEnc( RTL_TEXTENCODING_DONTKNOW )
513 ApiFontData::ApiFontData() :
514 maDesc(
515 "Calibri",
516 220, // height 11 points
518 OUString(),
519 css::awt::FontFamily::DONTKNOW,
520 RTL_TEXTENCODING_DONTKNOW,
521 css::awt::FontPitch::DONTKNOW,
522 100.0,
523 css::awt::FontWeight::NORMAL,
524 css::awt::FontSlant_NONE,
525 css::awt::FontUnderline::NONE,
526 css::awt::FontStrikeout::NONE,
527 0.0,
528 false,
529 false,
530 css::awt::FontType::DONTKNOW ),
531 mnColor( API_RGB_TRANSPARENT ),
532 mnEscapement( API_ESCAPE_NONE ),
533 mnEscapeHeight( API_ESCAPEHEIGHT_NONE ),
534 mbOutline( false ),
535 mbShadow( false )
537 maLatinFont.maName = maDesc.Name;
540 Font::Font( const WorkbookHelper& rHelper, bool bDxf ) :
541 WorkbookHelper( rHelper ),
542 maModel( rHelper.getTheme().getDefaultFontModel() ),
543 maUsedFlags( !bDxf ),
544 mbDxf( bDxf )
548 Font::Font( const WorkbookHelper& rHelper, const FontModel& rModel ) :
549 WorkbookHelper( rHelper ),
550 maModel( rModel ),
551 maUsedFlags( true ),
552 mbDxf( false )
556 void Font::importAttribs( sal_Int32 nElement, const AttributeList& rAttribs )
558 const FontModel& rDefModel = getTheme().getDefaultFontModel();
559 switch( nElement )
561 case XLS_TOKEN( name ): // when in <font> element
562 case XLS_TOKEN( rFont ): // when in <rPr> element
563 if( rAttribs.hasAttribute( XML_val ) )
565 maModel.maName = rAttribs.getXString( XML_val, OUString() );
566 maUsedFlags.mbNameUsed = true;
568 break;
569 case XLS_TOKEN( scheme ):
570 maModel.mnScheme = rAttribs.getToken( XML_val, rDefModel.mnScheme );
571 break;
572 case XLS_TOKEN( family ):
573 maModel.mnFamily = rAttribs.getInteger( XML_val, rDefModel.mnFamily );
574 break;
575 case XLS_TOKEN( charset ):
576 maModel.mnCharSet = rAttribs.getInteger( XML_val, rDefModel.mnCharSet );
577 break;
578 case XLS_TOKEN( sz ):
579 maModel.mfHeight = rAttribs.getDouble( XML_val, rDefModel.mfHeight );
580 maUsedFlags.mbHeightUsed = true;
581 break;
582 case XLS_TOKEN( color ):
583 maModel.maColor.importColor( rAttribs );
584 maUsedFlags.mbColorUsed = true;
585 break;
586 case XLS_TOKEN( u ):
587 maModel.mnUnderline = rAttribs.getToken( XML_val, XML_single );
588 maUsedFlags.mbUnderlineUsed = true;
589 break;
590 case XLS_TOKEN( vertAlign ):
591 maModel.mnEscapement = rAttribs.getToken( XML_val, XML_baseline );
592 maUsedFlags.mbEscapementUsed = true;
593 break;
594 case XLS_TOKEN( b ):
595 maModel.mbBold = rAttribs.getBool( XML_val, true );
596 maUsedFlags.mbWeightUsed = true;
597 break;
598 case XLS_TOKEN( i ):
599 maModel.mbItalic = rAttribs.getBool( XML_val, true );
600 maUsedFlags.mbPostureUsed = true;
601 break;
602 case XLS_TOKEN( strike ):
603 maModel.mbStrikeout = rAttribs.getBool( XML_val, true );
604 maUsedFlags.mbStrikeoutUsed = true;
605 break;
606 case XLS_TOKEN( outline ):
607 maModel.mbOutline = rAttribs.getBool( XML_val, true );
608 maUsedFlags.mbOutlineUsed = true;
609 break;
610 case XLS_TOKEN( shadow ):
611 maModel.mbShadow = rAttribs.getBool( XML_val, true );
612 maUsedFlags.mbShadowUsed = true;
613 break;
617 void Font::importFont( SequenceInputStream& rStrm )
619 SAL_WARN_IF( mbDxf, "sc", "Font::importFont - unexpected conditional formatting flag" );
621 sal_uInt16 nHeight, nFlags, nWeight, nEscapement;
622 sal_uInt8 nUnderline, nFamily, nCharSet, nScheme;
623 nHeight = rStrm.readuInt16();
624 nFlags = rStrm.readuInt16();
625 nWeight = rStrm.readuInt16();
626 nEscapement = rStrm.readuInt16();
627 nUnderline = rStrm.readuChar();
628 nFamily = rStrm.readuChar();
629 nCharSet = rStrm.readuChar();
630 rStrm.skip( 1 );
631 rStrm >> maModel.maColor;
632 nScheme = rStrm.readuChar();
633 rStrm >> maModel.maName;
635 // equal constants in all BIFFs for weight, underline, and escapement
636 maModel.setBiff12Scheme( nScheme );
637 maModel.setBiffHeight( nHeight );
638 maModel.setBiffWeight( nWeight );
639 maModel.setBiffUnderline( nUnderline );
640 maModel.setBiffEscapement( nEscapement );
641 maModel.mnFamily = nFamily;
642 maModel.mnCharSet = nCharSet;
643 // equal flags in all BIFFs
644 maModel.mbItalic = getFlag( nFlags, BIFF_FONTFLAG_ITALIC );
645 maModel.mbStrikeout = getFlag( nFlags, BIFF_FONTFLAG_STRIKEOUT );
646 maModel.mbOutline = getFlag( nFlags, BIFF_FONTFLAG_OUTLINE );
647 maModel.mbShadow = getFlag( nFlags, BIFF_FONTFLAG_SHADOW );
650 void Font::importDxfName( SequenceInputStream& rStrm )
652 SAL_WARN_IF( !mbDxf, "sc", "Font::importDxfName - missing conditional formatting flag" );
653 maModel.maName = BiffHelper::readString( rStrm, false );
654 maUsedFlags.mbColorUsed = true;
657 void Font::importDxfColor( SequenceInputStream& rStrm )
659 SAL_WARN_IF( !mbDxf, "sc", "Font::importDxfColor - missing conditional formatting flag" );
660 rStrm >> maModel.maColor;
661 maUsedFlags.mbColorUsed = true;
664 void Font::importDxfScheme( SequenceInputStream& rStrm )
666 SAL_WARN_IF( !mbDxf, "sc", "Font::importDxfScheme - missing conditional formatting flag" );
667 maModel.setBiff12Scheme( rStrm.readuInt8() );
668 maUsedFlags.mbSchemeUsed = true;
671 void Font::importDxfHeight( SequenceInputStream& rStrm )
673 SAL_WARN_IF( !mbDxf, "sc", "Font::importDxfHeight - missing conditional formatting flag" );
674 maModel.setBiffHeight( rStrm.readuInt16() );
675 maUsedFlags.mbHeightUsed = true;
678 void Font::importDxfWeight( SequenceInputStream& rStrm )
680 SAL_WARN_IF( !mbDxf, "sc", "Font::importDxfWeight - missing conditional formatting flag" );
681 maModel.setBiffWeight( rStrm.readuInt16() );
682 maUsedFlags.mbWeightUsed = true;
685 void Font::importDxfUnderline( SequenceInputStream& rStrm )
687 SAL_WARN_IF( !mbDxf, "sc", "Font::importDxfUnderline - missing conditional formatting flag" );
688 maModel.setBiffUnderline( rStrm.readuInt16() );
689 maUsedFlags.mbUnderlineUsed = true;
692 void Font::importDxfEscapement( SequenceInputStream& rStrm )
694 SAL_WARN_IF( !mbDxf, "sc", "Font::importDxfEscapement - missing conditional formatting flag" );
695 maModel.setBiffEscapement( rStrm.readuInt16() );
696 maUsedFlags.mbEscapementUsed = true;
699 void Font::importDxfFlag( sal_Int32 nElement, SequenceInputStream& rStrm )
701 SAL_WARN_IF( !mbDxf, "sc", "Font::importDxfFlag - missing conditional formatting flag" );
702 bool bFlag = rStrm.readuInt8() != 0;
703 switch( nElement )
705 case XML_i:
706 maModel.mbItalic = bFlag;
707 maUsedFlags.mbPostureUsed = true;
708 break;
709 case XML_strike:
710 maModel.mbStrikeout = bFlag;
711 maUsedFlags.mbStrikeoutUsed = true;
712 break;
713 case XML_outline:
714 maModel.mbOutline = bFlag;
715 maUsedFlags.mbOutlineUsed = true;
716 break;
717 case XML_shadow:
718 maModel.mbShadow = bFlag;
719 maUsedFlags.mbShadowUsed = true;
720 break;
721 default:
722 OSL_FAIL( "Font::importDxfFlag - unexpected element identifier" );
726 void Font::finalizeImport()
728 // font name
729 maApiData.maDesc.Name = maModel.maName;
731 // font family
732 switch( maModel.mnFamily )
734 case OOX_FONTFAMILY_NONE: maApiData.maDesc.Family = css::awt::FontFamily::DONTKNOW; break;
735 case OOX_FONTFAMILY_ROMAN: maApiData.maDesc.Family = css::awt::FontFamily::ROMAN; break;
736 case OOX_FONTFAMILY_SWISS: maApiData.maDesc.Family = css::awt::FontFamily::SWISS; break;
737 case OOX_FONTFAMILY_MODERN: maApiData.maDesc.Family = css::awt::FontFamily::MODERN; break;
738 case OOX_FONTFAMILY_SCRIPT: maApiData.maDesc.Family = css::awt::FontFamily::SCRIPT; break;
739 case OOX_FONTFAMILY_DECORATIVE: maApiData.maDesc.Family = css::awt::FontFamily::DECORATIVE; break;
742 // character set (API font descriptor uses rtl_TextEncoding in member CharSet!)
743 if( (0 <= maModel.mnCharSet) && (maModel.mnCharSet <= SAL_MAX_UINT8) )
744 maApiData.maDesc.CharSet = static_cast< sal_Int16 >(
745 rtl_getTextEncodingFromWindowsCharset( static_cast< sal_uInt8 >( maModel.mnCharSet ) ) );
747 // color, height, weight, slant, strikeout, outline, shadow
748 maApiData.mnColor = maModel.maColor.getColor( getBaseFilter().getGraphicHelper() );
749 maApiData.maDesc.Height = static_cast< sal_Int16 >( maModel.mfHeight * 20.0 );
750 maApiData.maDesc.Weight = maModel.mbBold ? css::awt::FontWeight::BOLD : css::awt::FontWeight::NORMAL;
751 maApiData.maDesc.Slant = maModel.mbItalic ? css::awt::FontSlant_ITALIC : css::awt::FontSlant_NONE;
752 maApiData.maDesc.Strikeout = maModel.mbStrikeout ? css::awt::FontStrikeout::SINGLE : css::awt::FontStrikeout::NONE;
753 maApiData.mbOutline = maModel.mbOutline;
754 maApiData.mbShadow = maModel.mbShadow;
756 // underline
757 switch( maModel.mnUnderline )
759 case XML_double: maApiData.maDesc.Underline = css::awt::FontUnderline::DOUBLE; break;
760 case XML_doubleAccounting: maApiData.maDesc.Underline = css::awt::FontUnderline::DOUBLE; break;
761 case XML_none: maApiData.maDesc.Underline = css::awt::FontUnderline::NONE; break;
762 case XML_single: maApiData.maDesc.Underline = css::awt::FontUnderline::SINGLE; break;
763 case XML_singleAccounting: maApiData.maDesc.Underline = css::awt::FontUnderline::SINGLE; break;
766 // escapement
767 switch( maModel.mnEscapement )
769 case XML_baseline:
770 maApiData.mnEscapement = API_ESCAPE_NONE;
771 maApiData.mnEscapeHeight = API_ESCAPEHEIGHT_NONE;
772 break;
773 case XML_superscript:
774 maApiData.mnEscapement = API_ESCAPE_SUPERSCRIPT;
775 maApiData.mnEscapeHeight = API_ESCAPEHEIGHT_DEFAULT;
776 break;
777 case XML_subscript:
778 maApiData.mnEscapement = API_ESCAPE_SUBSCRIPT;
779 maApiData.mnEscapeHeight = API_ESCAPEHEIGHT_DEFAULT;
780 break;
783 // supported script types
784 if( maUsedFlags.mbNameUsed )
786 PropertySet aDocProps( getDocument() );
787 Reference< XDevice > xDevice( aDocProps.getAnyProperty( PROP_ReferenceDevice ), UNO_QUERY );
788 if( xDevice.is() )
790 Reference< XFont2 > xFont( xDevice->getFont( maApiData.maDesc ), UNO_QUERY );
791 if( xFont.is() )
793 // #91658# CJK fonts
794 bool bHasAsian =
795 xFont->hasGlyphs( OUString( u'\x3041' ) ) || // 3040-309F: Hiragana
796 xFont->hasGlyphs( OUString( u'\x30A1' ) ) || // 30A0-30FF: Katakana
797 xFont->hasGlyphs( OUString( u'\x3111' ) ) || // 3100-312F: Bopomofo
798 xFont->hasGlyphs( OUString( u'\x3131' ) ) || // 3130-318F: Hangul Compatibility Jamo
799 xFont->hasGlyphs( OUString( u'\x3301' ) ) || // 3300-33FF: CJK Compatibility
800 xFont->hasGlyphs( OUString( u'\x3401' ) ) || // 3400-4DBF: CJK Unified Ideographs Extension A
801 xFont->hasGlyphs( OUString( u'\x4E01' ) ) || // 4E00-9FFF: CJK Unified Ideographs
802 xFont->hasGlyphs( OUString( u'\x7E01' ) ) || // 4E00-9FFF: CJK Unified Ideographs
803 xFont->hasGlyphs( OUString( u'\xA001' ) ) || // A001-A48F: Yi Syllables
804 xFont->hasGlyphs( OUString( u'\xAC01' ) ) || // AC00-D7AF: Hangul Syllables
805 xFont->hasGlyphs( OUString( u'\xCC01' ) ) || // AC00-D7AF: Hangul Syllables
806 xFont->hasGlyphs( OUString( u'\xF901' ) ) || // F900-FAFF: CJK Compatibility Ideographs
807 xFont->hasGlyphs( OUString( u'\xFF71' ) ); // FF00-FFEF: Halfwidth/Fullwidth Forms
808 // #113783# CTL fonts
809 bool bHasCmplx =
810 xFont->hasGlyphs( OUString( u'\x05D1' ) ) || // 0590-05FF: Hebrew
811 xFont->hasGlyphs( OUString( u'\x0631' ) ) || // 0600-06FF: Arabic
812 xFont->hasGlyphs( OUString( u'\x0721' ) ) || // 0700-074F: Syriac
813 xFont->hasGlyphs( OUString( u'\x0911' ) ) || // 0900-0DFF: Indic scripts
814 xFont->hasGlyphs( OUString( u'\x0E01' ) ) || // 0E00-0E7F: Thai
815 xFont->hasGlyphs( OUString( u'\xFB21' ) ) || // FB1D-FB4F: Hebrew Presentation Forms
816 xFont->hasGlyphs( OUString( u'\xFB51' ) ) || // FB50-FDFF: Arabic Presentation Forms-A
817 xFont->hasGlyphs( OUString( u'\xFE71' ) ); // FE70-FEFF: Arabic Presentation Forms-B
818 // Western fonts
819 bool bHasLatin =
820 (!bHasAsian && !bHasCmplx) ||
821 xFont->hasGlyphs( OUString( 'A' ) );
823 lclSetFontName( maApiData.maLatinFont, maApiData.maDesc, bHasLatin );
824 lclSetFontName( maApiData.maAsianFont, maApiData.maDesc, bHasAsian );
825 lclSetFontName( maApiData.maCmplxFont, maApiData.maDesc, bHasCmplx );
831 bool Font::needsRichTextFormat() const
833 return maApiData.mnEscapement != API_ESCAPE_NONE;
836 static ::FontFamily lcl_getFontFamily( sal_Int32 nFamily )
838 ::FontFamily eScFamily = FAMILY_DONTKNOW;
839 switch( nFamily )
841 case css::awt::FontFamily::DONTKNOW:
842 eScFamily = FAMILY_DONTKNOW;
843 break;
844 case css::awt::FontFamily::ROMAN:
845 eScFamily = FAMILY_ROMAN;
846 break;
847 case css::awt::FontFamily::SWISS:
848 eScFamily = FAMILY_SWISS;
849 break;
850 case css::awt::FontFamily::MODERN:
851 eScFamily = FAMILY_MODERN;
852 break;
853 case css::awt::FontFamily::SCRIPT:
854 eScFamily = FAMILY_SCRIPT;
855 break;
856 case css::awt::FontFamily::DECORATIVE:
857 eScFamily = FAMILY_DECORATIVE;
858 break;
860 return eScFamily;
863 void Font::fillToItemSet( SfxItemSet& rItemSet, bool bEditEngineText, bool bSkipPoolDefs ) const
865 if ( maUsedFlags.mbNameUsed )
867 if( !maApiData.maLatinFont.maName.isEmpty() )
869 rtl_TextEncoding eFontEnc = maApiData.maLatinFont.mnTextEnc;
870 // taken from binary importer
871 rtl_TextEncoding eTempTextEnc = (bEditEngineText && (eFontEnc == getTextEncoding())) ?
872 ScfTools::GetSystemTextEncoding() : eFontEnc;
874 SvxFontItem aFontItem( lcl_getFontFamily( maApiData.maLatinFont.mnFamily ), maApiData.maLatinFont.maName, OUString(),
875 PITCH_DONTKNOW, eTempTextEnc, ATTR_FONT );
876 ScfTools::PutItem( rItemSet, aFontItem, bEditEngineText ? static_cast<sal_uInt16>(EE_CHAR_FONTINFO) : ATTR_FONT, bSkipPoolDefs );
878 if( !maApiData.maAsianFont.maName.isEmpty() )
880 rtl_TextEncoding eFontEnc = maApiData.maAsianFont.mnTextEnc;
881 // taken from binary importer
882 rtl_TextEncoding eTempTextEnc = (bEditEngineText && (eFontEnc == getTextEncoding())) ?
883 ScfTools::GetSystemTextEncoding() : eFontEnc;
884 SvxFontItem aFontItem( lcl_getFontFamily( maApiData.maAsianFont.mnFamily ), maApiData.maAsianFont.maName, OUString(),
885 PITCH_DONTKNOW, eTempTextEnc, ATTR_FONT );
886 ScfTools::PutItem( rItemSet, aFontItem, bEditEngineText ? static_cast<sal_uInt16>(EE_CHAR_FONTINFO_CJK) : ATTR_CJK_FONT, bSkipPoolDefs );
888 if( !maApiData.maCmplxFont.maName.isEmpty() )
890 rtl_TextEncoding eFontEnc = maApiData.maCmplxFont.mnTextEnc;
891 // taken from binary importer
892 rtl_TextEncoding eTempTextEnc = (bEditEngineText && (eFontEnc == getTextEncoding())) ?
893 ScfTools::GetSystemTextEncoding() : eFontEnc;
894 SvxFontItem aFontItem( lcl_getFontFamily( maApiData.maCmplxFont.mnFamily ), maApiData.maCmplxFont.maName, OUString(),
895 PITCH_DONTKNOW, eTempTextEnc, ATTR_FONT );
896 ScfTools::PutItem( rItemSet, aFontItem, bEditEngineText ? static_cast<sal_uInt16>(EE_CHAR_FONTINFO_CTL) : ATTR_CTL_FONT, bSkipPoolDefs );
899 // font height
900 if( maUsedFlags.mbHeightUsed )
902 sal_Int32 nHeight = maApiData.maDesc.Height;
903 // do we use XclFontItemType::HeaderFooter ( or is it just relevant for the binary filter )
904 if( bEditEngineText/* && (eType != XclFontItemType::HeaderFooter) */) // do not convert header/footer height
905 nHeight = (nHeight * 127 + 36) / EXC_POINTS_PER_INCH; // 1 in == 72 pt
906 SvxFontHeightItem aHeightItem( nHeight, 100, ATTR_FONT_HEIGHT );
907 ScfTools::PutItem( rItemSet, aHeightItem, bEditEngineText ? static_cast<sal_uInt16>(EE_CHAR_FONTHEIGHT) : ATTR_FONT_HEIGHT, bSkipPoolDefs );
908 ScfTools::PutItem( rItemSet, aHeightItem, bEditEngineText ? static_cast<sal_uInt16>(EE_CHAR_FONTHEIGHT_CJK) : ATTR_CJK_FONT_HEIGHT, bSkipPoolDefs );
909 ScfTools::PutItem( rItemSet, aHeightItem, bEditEngineText ? static_cast<sal_uInt16>(EE_CHAR_FONTHEIGHT_CTL) : ATTR_CTL_FONT_HEIGHT, bSkipPoolDefs );
911 // font weight
912 if( maUsedFlags.mbWeightUsed )
914 ::FontWeight fWeight = vcl::unohelper::ConvertFontWeight( maApiData.maDesc.Weight );
915 SvxWeightItem aWeightItem( fWeight, ATTR_FONT_WEIGHT );
916 ScfTools::PutItem( rItemSet, aWeightItem, bEditEngineText ? static_cast<sal_uInt16>(EE_CHAR_WEIGHT) : ATTR_FONT_WEIGHT, bSkipPoolDefs );
917 ScfTools::PutItem( rItemSet, aWeightItem, bEditEngineText ? static_cast<sal_uInt16>(EE_CHAR_WEIGHT_CTL) : ATTR_CTL_FONT_WEIGHT, bSkipPoolDefs );
918 ScfTools::PutItem( rItemSet, aWeightItem, bEditEngineText ? static_cast<sal_uInt16>(EE_CHAR_WEIGHT_CJK) : ATTR_CJK_FONT_WEIGHT, bSkipPoolDefs );
920 // font posture
921 if( maUsedFlags.mbPostureUsed )
923 SvxPostureItem aPostItem( ( maApiData.maDesc.Slant == css::awt::FontSlant_ITALIC ) ? ITALIC_NORMAL : ITALIC_NONE, ATTR_FONT_POSTURE);
924 ScfTools::PutItem( rItemSet, aPostItem, bEditEngineText ? static_cast<sal_uInt16>(EE_CHAR_ITALIC) : ATTR_FONT_POSTURE, bSkipPoolDefs );
925 ScfTools::PutItem( rItemSet, aPostItem, bEditEngineText ? static_cast<sal_uInt16>(EE_CHAR_ITALIC_CJK) : ATTR_CJK_FONT_POSTURE, bSkipPoolDefs );
926 ScfTools::PutItem( rItemSet, aPostItem, bEditEngineText ? static_cast<sal_uInt16>(EE_CHAR_ITALIC_CTL) : ATTR_CTL_FONT_POSTURE, bSkipPoolDefs );
928 // character color
929 if( maUsedFlags.mbColorUsed )
931 ScfTools::PutItem( rItemSet,SvxColorItem( maApiData.mnColor, bEditEngineText ? static_cast<sal_uInt16>(EE_CHAR_COLOR) : ATTR_FONT_COLOR), bSkipPoolDefs );
933 // underline style
934 if( maUsedFlags.mbUnderlineUsed )
936 FontLineStyle eScUnderl;
937 if ( maApiData.maDesc.Underline == css::awt::FontUnderline::DOUBLE )
938 eScUnderl = LINESTYLE_DOUBLE;
939 else if ( maApiData.maDesc.Underline == css::awt::FontUnderline::SINGLE )
940 eScUnderl = LINESTYLE_SINGLE;
941 else
942 eScUnderl = LINESTYLE_NONE;
943 SvxUnderlineItem aUnderlItem( eScUnderl, ATTR_FONT_UNDERLINE );
944 ScfTools::PutItem( rItemSet, aUnderlItem, bEditEngineText ? static_cast<sal_uInt16>(EE_CHAR_UNDERLINE) : ATTR_FONT_UNDERLINE, bSkipPoolDefs );
946 // strike out style
947 if( maUsedFlags.mbStrikeoutUsed )
949 ScfTools::PutItem( rItemSet, SvxCrossedOutItem( maModel.mbStrikeout ? STRIKEOUT_SINGLE : STRIKEOUT_NONE, bEditEngineText ? static_cast<sal_uInt16>(EE_CHAR_STRIKEOUT) : ATTR_FONT_CROSSEDOUT ), bEditEngineText ? static_cast<sal_uInt16>(EE_CHAR_STRIKEOUT) : ATTR_FONT_CROSSEDOUT, bSkipPoolDefs );
952 // outline style
953 if( maUsedFlags.mbOutlineUsed )
955 ScfTools::PutItem( rItemSet, SvxContourItem( maApiData.mbOutline, ATTR_FONT_CONTOUR ), bEditEngineText ? static_cast<sal_uInt16>(EE_CHAR_OUTLINE) : ATTR_FONT_CONTOUR, bSkipPoolDefs );
958 // shadow style
959 if( maUsedFlags.mbShadowUsed )
961 ScfTools::PutItem( rItemSet, SvxShadowedItem( maApiData.mbShadow, ATTR_FONT_SHADOWED ), bEditEngineText ? static_cast<sal_uInt16>(EE_CHAR_SHADOW) : ATTR_FONT_SHADOWED, bSkipPoolDefs );
963 if( maUsedFlags.mbEscapementUsed )
965 SvxEscapement eScEscapem = SvxEscapement::Off;
966 if ( maApiData.mnEscapement == API_ESCAPE_SUPERSCRIPT )
967 eScEscapem = SvxEscapement::Superscript;
968 else if ( maApiData.mnEscapement == API_ESCAPE_SUBSCRIPT )
969 eScEscapem = SvxEscapement::Subscript;
970 if( bEditEngineText )
972 // #TODO handle EscapementHeight
973 rItemSet.Put( SvxEscapementItem( eScEscapem, EE_CHAR_ESCAPEMENT ) );
978 void Font::writeToPropertyMap( PropertyMap& rPropMap ) const
980 // font name properties
981 if( maUsedFlags.mbNameUsed )
983 if( !maApiData.maLatinFont.maName.isEmpty() )
985 rPropMap.setProperty( PROP_CharFontName, maApiData.maLatinFont.maName);
986 rPropMap.setProperty( PROP_CharFontFamily, maApiData.maLatinFont.mnFamily);
987 rPropMap.setProperty( PROP_CharFontCharSet, maApiData.maLatinFont.mnTextEnc);
989 if( !maApiData.maAsianFont.maName.isEmpty() )
991 rPropMap.setProperty( PROP_CharFontNameAsian, maApiData.maAsianFont.maName);
992 rPropMap.setProperty( PROP_CharFontFamilyAsian, maApiData.maAsianFont.mnFamily);
993 rPropMap.setProperty( PROP_CharFontCharSetAsian, maApiData.maAsianFont.mnTextEnc);
995 if( !maApiData.maCmplxFont.maName.isEmpty() )
997 rPropMap.setProperty( PROP_CharFontNameComplex, maApiData.maCmplxFont.maName);
998 rPropMap.setProperty( PROP_CharFontFamilyComplex, maApiData.maCmplxFont.mnFamily);
999 rPropMap.setProperty( PROP_CharFontCharSetComplex, maApiData.maCmplxFont.mnTextEnc);
1002 // font height
1003 if( maUsedFlags.mbHeightUsed )
1005 float fHeight = static_cast< float >( maApiData.maDesc.Height / 20.0 ); // twips to points
1006 rPropMap.setProperty( PROP_CharHeight, fHeight);
1007 rPropMap.setProperty( PROP_CharHeightAsian, fHeight);
1008 rPropMap.setProperty( PROP_CharHeightComplex, fHeight);
1010 // font weight
1011 if( maUsedFlags.mbWeightUsed )
1013 float fWeight = maApiData.maDesc.Weight;
1014 rPropMap.setProperty( PROP_CharWeight, fWeight);
1015 rPropMap.setProperty( PROP_CharWeightAsian, fWeight);
1016 rPropMap.setProperty( PROP_CharWeightComplex, fWeight);
1018 // font posture
1019 if( maUsedFlags.mbPostureUsed )
1021 rPropMap.setProperty( PROP_CharPosture, maApiData.maDesc.Slant);
1022 rPropMap.setProperty( PROP_CharPostureAsian, maApiData.maDesc.Slant);
1023 rPropMap.setProperty( PROP_CharPostureComplex, maApiData.maDesc.Slant);
1025 // character color
1026 if( maUsedFlags.mbColorUsed )
1027 rPropMap.setProperty( PROP_CharColor, maApiData.mnColor);
1028 // underline style
1029 if( maUsedFlags.mbUnderlineUsed )
1030 rPropMap.setProperty( PROP_CharUnderline, maApiData.maDesc.Underline);
1031 // strike out style
1032 if( maUsedFlags.mbStrikeoutUsed )
1033 rPropMap.setProperty( PROP_CharStrikeout, maApiData.maDesc.Strikeout);
1034 // outline style
1035 if( maUsedFlags.mbOutlineUsed )
1036 rPropMap.setProperty( PROP_CharContoured, maApiData.mbOutline);
1037 // shadow style
1038 if( maUsedFlags.mbShadowUsed )
1039 rPropMap.setProperty( PROP_CharShadowed, maApiData.mbShadow);
1040 // escapement
1041 if( maUsedFlags.mbEscapementUsed )
1043 rPropMap.setProperty( PROP_CharEscapement, maApiData.mnEscapement);
1044 rPropMap.setProperty( PROP_CharEscapementHeight, maApiData.mnEscapeHeight);
1048 void Font::writeToPropertySet( PropertySet& rPropSet ) const
1050 PropertyMap aPropMap;
1051 writeToPropertyMap( aPropMap );
1052 rPropSet.setProperties( aPropMap );
1055 AlignmentModel::AlignmentModel() :
1056 mnHorAlign( XML_general ),
1057 mnVerAlign( XML_bottom ),
1058 mnTextDir( OOX_XF_TEXTDIR_CONTEXT ),
1059 mnRotation( OOX_XF_ROTATION_NONE ),
1060 mnIndent( OOX_XF_INDENT_NONE ),
1061 mbWrapText( false ),
1062 mbShrink( false ),
1063 mbJustLastLine( false )
1067 void AlignmentModel::setBiffHorAlign( sal_uInt8 nHorAlign )
1069 static const sal_Int32 spnHorAligns[] = {
1070 XML_general, XML_left, XML_center, XML_right,
1071 XML_fill, XML_justify, XML_centerContinuous, XML_distributed };
1072 mnHorAlign = STATIC_ARRAY_SELECT( spnHorAligns, nHorAlign, XML_general );
1075 void AlignmentModel::setBiffVerAlign( sal_uInt8 nVerAlign )
1077 static const sal_Int32 spnVerAligns[] = {
1078 XML_top, XML_center, XML_bottom, XML_justify, XML_distributed };
1079 mnVerAlign = STATIC_ARRAY_SELECT( spnVerAligns, nVerAlign, XML_bottom );
1082 ApiAlignmentData::ApiAlignmentData() :
1083 meHorJustify( css::table::CellHoriJustify_STANDARD ),
1084 mnHorJustifyMethod( css::table::CellJustifyMethod::AUTO ),
1085 mnVerJustify( css::table::CellVertJustify2::STANDARD ),
1086 mnVerJustifyMethod( css::table::CellJustifyMethod::AUTO ),
1087 meOrientation( css::table::CellOrientation_STANDARD ),
1088 mnRotation( 0 ),
1089 mnWritingMode( css::text::WritingMode2::PAGE ),
1090 mnIndent( 0 ),
1091 mbWrapText( false ),
1092 mbShrink( false )
1096 bool operator==( const ApiAlignmentData& rLeft, const ApiAlignmentData& rRight )
1098 return
1099 (rLeft.meHorJustify == rRight.meHorJustify) &&
1100 (rLeft.mnHorJustifyMethod == rRight.mnHorJustifyMethod) &&
1101 (rLeft.mnVerJustify == rRight.mnVerJustify) &&
1102 (rLeft.mnVerJustifyMethod == rRight.mnVerJustifyMethod) &&
1103 (rLeft.meOrientation == rRight.meOrientation) &&
1104 (rLeft.mnRotation == rRight.mnRotation) &&
1105 (rLeft.mnWritingMode == rRight.mnWritingMode) &&
1106 (rLeft.mnIndent == rRight.mnIndent) &&
1107 (rLeft.mbWrapText == rRight.mbWrapText) &&
1108 (rLeft.mbShrink == rRight.mbShrink);
1111 Alignment::Alignment( const WorkbookHelper& rHelper ) :
1112 WorkbookHelper( rHelper )
1116 void Alignment::importAlignment( const AttributeList& rAttribs )
1118 maModel.mnVerAlign = rAttribs.getToken( XML_vertical, XML_bottom );
1119 maModel.mnTextDir = rAttribs.getInteger( XML_readingOrder, OOX_XF_TEXTDIR_CONTEXT );
1120 maModel.mnRotation = rAttribs.getInteger( XML_textRotation, OOX_XF_ROTATION_NONE );
1121 sal_Int32 nDefaultHorAlign = XML_general;
1122 if (maModel.mnRotation != OOX_XF_ROTATION_NONE)
1124 if (maModel.mnRotation < 90 || maModel.mnRotation == 180)
1126 nDefaultHorAlign = XML_left;
1128 else
1130 nDefaultHorAlign = XML_right;
1133 maModel.mnHorAlign = rAttribs.getToken( XML_horizontal, nDefaultHorAlign );
1134 maModel.mnIndent = rAttribs.getInteger( XML_indent, OOX_XF_INDENT_NONE );
1135 maModel.mbWrapText = rAttribs.getBool( XML_wrapText, false );
1136 maModel.mbShrink = rAttribs.getBool( XML_shrinkToFit, false );
1137 maModel.mbJustLastLine = rAttribs.getBool( XML_justifyLastLine, false );
1140 void Alignment::setBiff12Data( sal_uInt32 nFlags )
1142 maModel.setBiffHorAlign( extractValue< sal_uInt8 >( nFlags, 16, 3 ) );
1143 maModel.setBiffVerAlign( extractValue< sal_uInt8 >( nFlags, 19, 3 ) );
1144 maModel.mnTextDir = extractValue< sal_Int32 >( nFlags, 26, 2 );
1145 maModel.mnRotation = extractValue< sal_Int32 >( nFlags, 0, 8 );
1146 maModel.mnIndent = extractValue< sal_uInt8 >( nFlags, 8, 8 );
1147 maModel.mbWrapText = getFlag( nFlags, BIFF12_XF_WRAPTEXT );
1148 maModel.mbShrink = getFlag( nFlags, BIFF12_XF_SHRINK );
1149 maModel.mbJustLastLine = getFlag( nFlags, BIFF12_XF_JUSTLASTLINE );
1152 void Alignment::finalizeImport()
1154 // horizontal alignment
1155 switch( maModel.mnHorAlign )
1157 case XML_center: maApiData.meHorJustify = css::table::CellHoriJustify_CENTER; break;
1158 case XML_centerContinuous: maApiData.meHorJustify = css::table::CellHoriJustify_CENTER; break;
1159 case XML_distributed: maApiData.meHorJustify = css::table::CellHoriJustify_BLOCK; break;
1160 case XML_fill: maApiData.meHorJustify = css::table::CellHoriJustify_REPEAT; break;
1161 case XML_general: maApiData.meHorJustify = css::table::CellHoriJustify_STANDARD; break;
1162 case XML_justify: maApiData.meHorJustify = css::table::CellHoriJustify_BLOCK; break;
1163 case XML_left: maApiData.meHorJustify = css::table::CellHoriJustify_LEFT; break;
1164 case XML_right: maApiData.meHorJustify = css::table::CellHoriJustify_RIGHT; break;
1167 if (maModel.mnHorAlign == XML_distributed)
1168 maApiData.mnHorJustifyMethod = css::table::CellJustifyMethod::DISTRIBUTE;
1170 // vertical alignment
1171 switch( maModel.mnVerAlign )
1173 case XML_bottom: maApiData.mnVerJustify = css::table::CellVertJustify2::BOTTOM; break;
1174 case XML_center: maApiData.mnVerJustify = css::table::CellVertJustify2::CENTER; break;
1175 case XML_distributed: maApiData.mnVerJustify = css::table::CellVertJustify2::BLOCK; break;
1176 case XML_justify: maApiData.mnVerJustify = css::table::CellVertJustify2::BLOCK; break;
1177 case XML_top: maApiData.mnVerJustify = css::table::CellVertJustify2::TOP; break;
1180 if (maModel.mnVerAlign == XML_distributed)
1181 maApiData.mnVerJustifyMethod = css::table::CellJustifyMethod::DISTRIBUTE;
1183 /* indentation: expressed as number of blocks of 3 space characters in
1184 OOXML. */
1185 sal_Int32 nIndent = getUnitConverter().scaleToMm100( 3.0 * maModel.mnIndent, Unit::Space );
1186 if( (0 <= nIndent) && (nIndent <= SAL_MAX_INT16) )
1187 maApiData.mnIndent = static_cast< sal_Int16 >( nIndent );
1189 // complex text direction
1190 switch( maModel.mnTextDir )
1192 case OOX_XF_TEXTDIR_CONTEXT: maApiData.mnWritingMode = css::text::WritingMode2::PAGE; break;
1193 case OOX_XF_TEXTDIR_LTR: maApiData.mnWritingMode = css::text::WritingMode2::LR_TB; break;
1194 case OOX_XF_TEXTDIR_RTL: maApiData.mnWritingMode = css::text::WritingMode2::RL_TB; break;
1197 // rotation: 0-90 means 0 to 90 degrees ccw, 91-180 means 1 to 90 degrees cw, 255 means stacked
1198 sal_Int32 nOoxRot = maModel.mnRotation;
1199 maApiData.mnRotation = ((0 <= nOoxRot) && (nOoxRot <= 90)) ?
1200 (100 * nOoxRot) :
1201 (((91 <= nOoxRot) && (nOoxRot <= 180)) ? (100 * (450 - nOoxRot)) : 0);
1203 // "Orientation" property used for character stacking
1204 maApiData.meOrientation = (nOoxRot == OOX_XF_ROTATION_STACKED) ?
1205 css::table::CellOrientation_STACKED : css::table::CellOrientation_STANDARD;
1207 // alignment flags (#i84960 automatic line break, if vertically justified/distributed)
1208 maApiData.mbWrapText = maModel.mbWrapText || (maModel.mnVerAlign == XML_distributed) || (maModel.mnVerAlign == XML_justify);
1209 maApiData.mbShrink = maModel.mbShrink;
1213 ::SvxCellVerJustify Alignment::GetScVerAlign() const
1215 ::SvxCellVerJustify nVert = ::SvxCellVerJustify::Standard;
1216 switch ( maApiData.mnVerJustify )
1218 case css::table::CellVertJustify2::BOTTOM:
1219 nVert = ::SvxCellVerJustify::Bottom;
1220 break;
1221 case css::table::CellVertJustify2::CENTER:
1222 nVert = ::SvxCellVerJustify::Center;
1223 break;
1224 case css::table::CellVertJustify2::TOP:
1225 nVert = ::SvxCellVerJustify::Top;
1226 break;
1227 case css::table::CellVertJustify2::BLOCK:
1228 nVert = ::SvxCellVerJustify::Block;
1229 break;
1230 case css::table::CellVertJustify2::STANDARD:
1231 default:
1232 nVert = ::SvxCellVerJustify::Standard;
1233 break;
1235 return nVert;
1238 ::SvxCellHorJustify Alignment::GetScHorAlign() const
1240 ::SvxCellHorJustify nHori = ::SvxCellHorJustify::Standard;
1241 switch( maApiData.meHorJustify )
1243 case css::table::CellHoriJustify_LEFT:
1244 nHori = ::SvxCellHorJustify::Left;
1245 break;
1246 case css::table::CellHoriJustify_CENTER:
1247 nHori = ::SvxCellHorJustify::Center;
1248 break;
1249 case css::table::CellHoriJustify_RIGHT:
1250 nHori = ::SvxCellHorJustify::Right;
1251 break;
1252 case css::table::CellHoriJustify_BLOCK:
1253 nHori = ::SvxCellHorJustify::Block;
1254 break;
1255 case css::table::CellHoriJustify_REPEAT:
1256 nHori = ::SvxCellHorJustify::Repeat;
1257 break;
1258 case css::table::CellHoriJustify_STANDARD:
1259 default:
1260 nHori = ::SvxCellHorJustify::Standard;
1261 break;
1263 return nHori;
1266 SvxFrameDirection Alignment::GetScFrameDir() const
1268 SvxFrameDirection eFrameDir = SvxFrameDirection::Environment;
1269 switch( maApiData.mnWritingMode )
1271 case css::text::WritingMode2::PAGE:
1272 eFrameDir = SvxFrameDirection::Environment;
1273 break;
1274 case css::text::WritingMode2::LR_TB:
1275 eFrameDir = SvxFrameDirection::Horizontal_LR_TB;
1276 break;
1277 case css::text::WritingMode2::RL_TB:
1278 eFrameDir = SvxFrameDirection::Horizontal_RL_TB;
1279 break;
1280 default:
1281 OSL_FAIL( "GetScFrameDir - unknown CTL text direction" );
1283 return eFrameDir;
1286 void Alignment::fillToItemSet( SfxItemSet& rItemSet, bool bSkipPoolDefs ) const
1288 // horizontal alignment
1289 ScfTools::PutItem( rItemSet, SvxHorJustifyItem( GetScHorAlign(), ATTR_HOR_JUSTIFY ), bSkipPoolDefs );
1290 ScfTools::PutItem( rItemSet, SvxJustifyMethodItem( ( maApiData.mnHorJustifyMethod == css::table::CellJustifyMethod::DISTRIBUTE ) ? ::SvxCellJustifyMethod::Distribute : ::SvxCellJustifyMethod::Auto, ATTR_HOR_JUSTIFY_METHOD ), bSkipPoolDefs );
1291 ScfTools::PutItem( rItemSet, SvxVerJustifyItem( GetScVerAlign(), ATTR_VER_JUSTIFY ), bSkipPoolDefs );
1292 // vertical alignment
1293 ScfTools::PutItem( rItemSet, SvxJustifyMethodItem( ( maApiData.mnVerJustifyMethod == css::table::CellJustifyMethod::DISTRIBUTE ) ? ::SvxCellJustifyMethod::Distribute : ::SvxCellJustifyMethod::Auto, ATTR_VER_JUSTIFY_METHOD ), bSkipPoolDefs );
1295 // CTL text direction
1296 ScfTools::PutItem( rItemSet, SvxFrameDirectionItem( GetScFrameDir(), ATTR_WRITINGDIR ), bSkipPoolDefs );
1297 // set an angle in the range from -90 to 90 degrees
1298 ScfTools::PutItem( rItemSet, SfxInt32Item( ATTR_ROTATE_VALUE, maApiData.mnRotation ), bSkipPoolDefs );
1299 // Orientation
1300 ScfTools::PutItem( rItemSet, SfxBoolItem( ATTR_STACKED, maApiData.meOrientation == css::table::CellOrientation_STACKED ), bSkipPoolDefs );
1301 // indent
1302 ScfTools::PutItem( rItemSet, SfxUInt16Item( ATTR_INDENT, maApiData.mnIndent ), bSkipPoolDefs );
1303 // line wrap
1304 ScfTools::PutItem( rItemSet, SfxBoolItem( ATTR_LINEBREAK, maApiData.mbWrapText ), bSkipPoolDefs );
1305 ScfTools::PutItem( rItemSet, SfxBoolItem( ATTR_SHRINKTOFIT, maApiData.mbShrink ), bSkipPoolDefs );
1308 ProtectionModel::ProtectionModel() :
1309 mbLocked( true ), // default in Excel and Calc
1310 mbHidden( false )
1314 ApiProtectionData::ApiProtectionData() :
1315 maCellProt( true, false, false, false )
1319 bool operator==( const ApiProtectionData& rLeft, const ApiProtectionData& rRight )
1321 return
1322 (rLeft.maCellProt.IsLocked == rRight.maCellProt.IsLocked) &&
1323 (rLeft.maCellProt.IsFormulaHidden == rRight.maCellProt.IsFormulaHidden) &&
1324 (rLeft.maCellProt.IsHidden == rRight.maCellProt.IsHidden) &&
1325 (rLeft.maCellProt.IsPrintHidden == rRight.maCellProt.IsPrintHidden);
1328 Protection::Protection( const WorkbookHelper& rHelper ) :
1329 WorkbookHelper( rHelper )
1333 void Protection::importProtection( const AttributeList& rAttribs )
1335 maModel.mbLocked = rAttribs.getBool( XML_locked, true );
1336 maModel.mbHidden = rAttribs.getBool( XML_hidden, false );
1339 void Protection::setBiff12Data( sal_uInt32 nFlags )
1341 maModel.mbLocked = getFlag( nFlags, BIFF12_XF_LOCKED );
1342 maModel.mbHidden = getFlag( nFlags, BIFF12_XF_HIDDEN );
1345 void Protection::finalizeImport()
1347 maApiData.maCellProt.IsLocked = maModel.mbLocked;
1348 maApiData.maCellProt.IsFormulaHidden = maModel.mbHidden;
1351 void Protection::fillToItemSet( SfxItemSet& rItemSet, bool bSkipPoolDefs ) const
1353 ScfTools::PutItem( rItemSet, ScProtectionAttr( maApiData.maCellProt.IsLocked, maApiData.maCellProt.IsFormulaHidden ), bSkipPoolDefs );
1356 namespace {
1358 bool lcl_isBorder(const css::table::BorderLine& rBorder)
1360 return (rBorder.InnerLineWidth > 0) || (rBorder.OuterLineWidth > 0);
1365 BorderLineModel::BorderLineModel( bool bDxf ) :
1366 mnStyle( XML_none ),
1367 mbUsed( !bDxf )
1369 maColor.setIndexed( OOX_COLOR_WINDOWTEXT );
1372 void BorderLineModel::setBiffStyle( sal_Int32 nLineStyle )
1374 static const sal_Int32 spnStyleIds[] = {
1375 XML_none, XML_thin, XML_medium, XML_dashed,
1376 XML_dotted, XML_thick, XML_double, XML_hair,
1377 XML_mediumDashed, XML_dashDot, XML_mediumDashDot, XML_dashDotDot,
1378 XML_mediumDashDotDot, XML_slantDashDot };
1379 mnStyle = STATIC_ARRAY_SELECT( spnStyleIds, nLineStyle, XML_none );
1382 BorderModel::BorderModel( bool bDxf ) :
1383 maLeft( bDxf ),
1384 maRight( bDxf ),
1385 maTop( bDxf ),
1386 maBottom( bDxf ),
1387 maDiagonal( bDxf ),
1388 mbDiagTLtoBR( false ),
1389 mbDiagBLtoTR( false )
1393 ApiBorderData::ApiBorderData() :
1394 mbBorderUsed( false ),
1395 mbDiagUsed( false )
1399 bool ApiBorderData::hasAnyOuterBorder() const
1401 return
1402 ( lcl_isBorder( maTop ) && maTop.OuterLineWidth > 0 ) ||
1403 ( lcl_isBorder( maBottom ) && maBottom.OuterLineWidth > 0 ) ||
1404 ( lcl_isBorder( maLeft ) && maLeft.OuterLineWidth > 0 ) ||
1405 ( lcl_isBorder( maRight ) && maRight.OuterLineWidth > 0 );
1408 namespace {
1410 void lclSetBorderLineWidth( BorderLine& rBorderLine,
1411 sal_Int16 nOuter, sal_Int16 nDist = API_LINE_NONE, sal_Int16 nInner = API_LINE_NONE )
1413 rBorderLine.OuterLineWidth = nOuter;
1414 rBorderLine.LineDistance = nDist;
1415 rBorderLine.InnerLineWidth = nInner;
1418 } // namespace
1420 Border::Border( const WorkbookHelper& rHelper, bool bDxf ) :
1421 WorkbookHelper( rHelper ),
1422 maModel( bDxf ),
1423 mbDxf( bDxf )
1427 void Border::importBorder( const AttributeList& rAttribs )
1429 maModel.mbDiagTLtoBR = rAttribs.getBool( XML_diagonalDown, false );
1430 maModel.mbDiagBLtoTR = rAttribs.getBool( XML_diagonalUp, false );
1433 void Border::importStyle( sal_Int32 nElement, const AttributeList& rAttribs )
1435 if( BorderLineModel* pBorderLine = getBorderLine( nElement ) )
1437 pBorderLine->mnStyle = rAttribs.getToken( XML_style, XML_none );
1438 pBorderLine->mbUsed = true;
1442 void Border::importColor( sal_Int32 nElement, const AttributeList& rAttribs )
1444 if( BorderLineModel* pBorderLine = getBorderLine( nElement ) )
1445 pBorderLine->maColor.importColor( rAttribs );
1448 void Border::importBorder( SequenceInputStream& rStrm )
1450 sal_uInt8 nFlags = rStrm.readuInt8();
1451 maModel.mbDiagTLtoBR = getFlag( nFlags, BIFF12_BORDER_DIAG_TLBR );
1452 maModel.mbDiagBLtoTR = getFlag( nFlags, BIFF12_BORDER_DIAG_BLTR );
1453 maModel.maTop.setBiffStyle( rStrm.readuInt16() );
1454 rStrm >> maModel.maTop.maColor;
1455 maModel.maBottom.setBiffStyle( rStrm.readuInt16() );
1456 rStrm >> maModel.maBottom.maColor;
1457 maModel.maLeft.setBiffStyle( rStrm.readuInt16() );
1458 rStrm >> maModel.maLeft.maColor;
1459 maModel.maRight.setBiffStyle( rStrm.readuInt16() );
1460 rStrm >> maModel.maRight.maColor;
1461 maModel.maDiagonal.setBiffStyle( rStrm.readuInt16() );
1462 rStrm >> maModel.maDiagonal.maColor;
1465 void Border::importDxfBorder( sal_Int32 nElement, SequenceInputStream& rStrm )
1467 SAL_WARN_IF( !mbDxf, "sc", "Border::importDxfBorder - missing conditional formatting flag" );
1468 if( BorderLineModel* pBorderLine = getBorderLine( nElement ) )
1470 sal_uInt16 nStyle;
1471 rStrm >> pBorderLine->maColor;
1472 nStyle = rStrm.readuInt16();
1473 pBorderLine->setBiffStyle( nStyle );
1474 pBorderLine->mbUsed = true;
1478 void Border::finalizeImport( bool bRTL )
1480 if ( bRTL )
1482 BorderLineModel aTmp = maModel.maLeft;
1483 maModel.maLeft = maModel.maRight;
1484 maModel.maRight = aTmp;
1486 maApiData.mbBorderUsed = maModel.maLeft.mbUsed || maModel.maRight.mbUsed || maModel.maTop.mbUsed || maModel.maBottom.mbUsed;
1487 maApiData.mbDiagUsed = maModel.maDiagonal.mbUsed;
1489 convertBorderLine( maApiData.maLeft, maModel.maLeft );
1490 convertBorderLine( maApiData.maRight, maModel.maRight );
1491 convertBorderLine( maApiData.maTop, maModel.maTop );
1492 convertBorderLine( maApiData.maBottom, maModel.maBottom );
1494 if( maModel.mbDiagTLtoBR )
1495 convertBorderLine( maApiData.maTLtoBR, maModel.maDiagonal );
1496 if( maModel.mbDiagBLtoTR )
1497 convertBorderLine( maApiData.maBLtoTR, maModel.maDiagonal );
1500 void Border::fillToItemSet( SfxItemSet& rItemSet, bool bSkipPoolDefs ) const
1502 if( maApiData.mbBorderUsed )
1504 SvxBoxItem aBoxItem( ATTR_BORDER );
1505 ::editeng::SvxBorderLine aLine;
1507 if (SvxBoxItem::LineToSvxLine(maApiData.maLeft, aLine, false))
1509 aBoxItem.SetLine( &aLine, SvxBoxItemLine::LEFT );
1511 if (SvxBoxItem::LineToSvxLine(maApiData.maRight, aLine, false))
1513 aBoxItem.SetLine( &aLine, SvxBoxItemLine::RIGHT );
1515 if (SvxBoxItem::LineToSvxLine(maApiData.maTop, aLine, false))
1517 aBoxItem.SetLine( &aLine, SvxBoxItemLine::TOP );
1519 if (SvxBoxItem::LineToSvxLine(maApiData.maBottom, aLine, false))
1521 aBoxItem.SetLine( &aLine, SvxBoxItemLine::BOTTOM );
1523 ScfTools::PutItem( rItemSet, aBoxItem, bSkipPoolDefs );
1525 if ( maApiData.mbDiagUsed )
1527 SvxLineItem aTLBRItem( ATTR_BORDER_TLBR );
1528 SvxLineItem aBLTRItem( ATTR_BORDER_BLTR );
1529 ::editeng::SvxBorderLine aLine;
1530 if (SvxBoxItem::LineToSvxLine(maApiData.maTLtoBR, aLine, false))
1532 aTLBRItem.SetLine( &aLine );
1534 if (SvxBoxItem::LineToSvxLine(maApiData.maBLtoTR, aLine, false))
1536 aBLTRItem.SetLine( &aLine );
1538 ScfTools::PutItem( rItemSet, aTLBRItem, bSkipPoolDefs );
1539 ScfTools::PutItem( rItemSet, aBLTRItem, bSkipPoolDefs );
1543 BorderLineModel* Border::getBorderLine( sal_Int32 nElement )
1545 switch( nElement )
1547 case XLS_TOKEN( left ): return &maModel.maLeft;
1548 case XLS_TOKEN( start ): return &maModel.maLeft;
1549 case XLS_TOKEN( right ): return &maModel.maRight;
1550 case XLS_TOKEN( end ): return &maModel.maRight;
1551 case XLS_TOKEN( top ): return &maModel.maTop;
1552 case XLS_TOKEN( bottom ): return &maModel.maBottom;
1553 case XLS_TOKEN( diagonal ): return &maModel.maDiagonal;
1555 return nullptr;
1558 bool Border::convertBorderLine( BorderLine2& rBorderLine, const BorderLineModel& rModel )
1560 // Document: sc/qa/unit/data/README.cellborders
1562 rBorderLine.Color = sal_Int32(rModel.maColor.getColor( getBaseFilter().getGraphicHelper(), API_RGB_BLACK ));
1563 switch( rModel.mnStyle )
1565 case XML_dashDot:
1566 lclSetBorderLineWidth( rBorderLine, API_LINE_THIN );
1567 rBorderLine.LineStyle = BorderLineStyle::DASH_DOT;
1568 break;
1569 case XML_dashDotDot:
1570 lclSetBorderLineWidth( rBorderLine, API_LINE_THIN );
1571 rBorderLine.LineStyle = BorderLineStyle::DASH_DOT_DOT;
1572 break;
1573 case XML_dashed:
1574 lclSetBorderLineWidth( rBorderLine, API_LINE_THIN );
1575 rBorderLine.LineStyle = BorderLineStyle::FINE_DASHED;
1576 break;
1577 case XML_dotted:
1578 lclSetBorderLineWidth( rBorderLine, API_LINE_THIN );
1579 rBorderLine.LineStyle = BorderLineStyle::DOTTED;
1580 break;
1581 case XML_double:
1582 lclSetBorderLineWidth( rBorderLine, 10, 15, 10 );
1583 rBorderLine.LineStyle = BorderLineStyle::DOUBLE_THIN;
1584 break;
1585 case XML_hair: lclSetBorderLineWidth( rBorderLine, API_LINE_HAIR ); break;
1586 case XML_medium: lclSetBorderLineWidth( rBorderLine, API_LINE_MEDIUM ); break;
1587 case XML_mediumDashDot:
1588 lclSetBorderLineWidth( rBorderLine, API_LINE_MEDIUM );
1589 rBorderLine.LineStyle = BorderLineStyle::DASH_DOT;
1590 break;
1591 case XML_mediumDashDotDot:
1592 lclSetBorderLineWidth( rBorderLine, API_LINE_MEDIUM );
1593 rBorderLine.LineStyle = BorderLineStyle::DASH_DOT_DOT;
1594 break;
1595 case XML_mediumDashed:
1596 lclSetBorderLineWidth( rBorderLine, API_LINE_MEDIUM );
1597 rBorderLine.LineStyle = BorderLineStyle::DASHED;
1598 break;
1599 case XML_none: lclSetBorderLineWidth( rBorderLine, API_LINE_NONE ); break;
1600 case XML_slantDashDot:
1601 lclSetBorderLineWidth( rBorderLine, API_LINE_MEDIUM );
1602 rBorderLine.LineStyle = BorderLineStyle::FINE_DASHED;
1603 break;
1604 case XML_thick: lclSetBorderLineWidth( rBorderLine, API_LINE_THICK ); break;
1605 case XML_thin: lclSetBorderLineWidth( rBorderLine, API_LINE_THIN ); break;
1606 default: lclSetBorderLineWidth( rBorderLine, API_LINE_NONE ); break;
1608 return rModel.mbUsed;
1611 PatternFillModel::PatternFillModel( bool bDxf ) :
1612 mnPattern( XML_none ),
1613 mbPattColorUsed( !bDxf ),
1614 mbFillColorUsed( !bDxf ),
1615 mbPatternUsed( !bDxf )
1617 maPatternColor.setIndexed( OOX_COLOR_WINDOWTEXT );
1618 maFillColor.setIndexed( OOX_COLOR_WINDOWBACK );
1621 void PatternFillModel::setBiffPattern( sal_Int32 nPattern )
1623 static const sal_Int32 spnPatternIds[] = {
1624 XML_none, XML_solid, XML_mediumGray, XML_darkGray,
1625 XML_lightGray, XML_darkHorizontal, XML_darkVertical, XML_darkDown,
1626 XML_darkUp, XML_darkGrid, XML_darkTrellis, XML_lightHorizontal,
1627 XML_lightVertical, XML_lightDown, XML_lightUp, XML_lightGrid,
1628 XML_lightTrellis, XML_gray125, XML_gray0625 };
1629 mnPattern = STATIC_ARRAY_SELECT( spnPatternIds, nPattern, XML_none );
1632 GradientFillModel::GradientFillModel() :
1633 mnType( XML_linear ),
1634 mfAngle( 0.0 ),
1635 mfLeft( 0.0 ),
1636 mfRight( 0.0 ),
1637 mfTop( 0.0 ),
1638 mfBottom( 0.0 )
1642 void GradientFillModel::readGradient( SequenceInputStream& rStrm )
1644 sal_Int32 nType;
1645 nType = rStrm.readInt32();
1646 mfAngle = rStrm.readDouble();
1647 mfLeft = rStrm.readDouble();
1648 mfRight = rStrm.readDouble();
1649 mfTop = rStrm.readDouble();
1650 mfBottom = rStrm.readDouble();
1651 static const sal_Int32 spnTypes[] = { XML_linear, XML_path };
1652 mnType = STATIC_ARRAY_SELECT( spnTypes, nType, XML_TOKEN_INVALID );
1655 void GradientFillModel::readGradientStop( SequenceInputStream& rStrm, bool bDxf )
1657 Color aColor;
1658 double fPosition;
1659 if( bDxf )
1661 rStrm.skip( 2 );
1662 fPosition = rStrm.readDouble();
1663 rStrm >> aColor;
1665 else
1667 rStrm >> aColor;
1668 fPosition = rStrm.readDouble();
1670 if( !rStrm.isEof() && (fPosition >= 0.0) )
1671 maColors[ fPosition ] = aColor;
1674 ApiSolidFillData::ApiSolidFillData() :
1675 mnColor( API_RGB_TRANSPARENT ),
1676 mbTransparent( true ),
1677 mbUsed( false )
1681 namespace {
1683 sal_Int32 lclGetMixedColorComp( sal_Int32 nPatt, sal_Int32 nFill, sal_Int32 nAlpha )
1685 return ((nPatt - nFill) * nAlpha) / 0x80 + nFill;
1688 ::Color lclGetMixedColor( ::Color nPattColor, ::Color nFillColor, sal_Int32 nAlpha )
1690 return ::Color(
1691 lclGetMixedColorComp( nPattColor.GetRed(), nFillColor.GetRed(), nAlpha ),
1692 lclGetMixedColorComp( nPattColor.GetGreen(), nFillColor.GetGreen(), nAlpha ),
1693 lclGetMixedColorComp( nPattColor.GetBlue(), nFillColor.GetBlue(), nAlpha ) );
1696 } // namespace
1698 Fill::Fill( const WorkbookHelper& rHelper, bool bDxf ) :
1699 WorkbookHelper( rHelper ),
1700 mbDxf( bDxf )
1704 void Fill::importPatternFill( const AttributeList& rAttribs )
1706 mxPatternModel.reset( new PatternFillModel( mbDxf ) );
1707 mxPatternModel->mnPattern = rAttribs.getToken( XML_patternType, XML_none );
1708 if( mbDxf )
1709 mxPatternModel->mbPatternUsed = rAttribs.hasAttribute( XML_patternType );
1712 void Fill::importFgColor( const AttributeList& rAttribs )
1714 OSL_ENSURE( mxPatternModel.get(), "Fill::importFgColor - missing pattern data" );
1715 if( mxPatternModel.get() )
1717 mxPatternModel->maPatternColor.importColor( rAttribs );
1718 mxPatternModel->mbPattColorUsed = true;
1722 void Fill::importBgColor( const AttributeList& rAttribs )
1724 OSL_ENSURE( mxPatternModel.get(), "Fill::importBgColor - missing pattern data" );
1725 if( mxPatternModel.get() )
1727 mxPatternModel->maFillColor.importColor( rAttribs );
1728 mxPatternModel->mbFillColorUsed = true;
1732 void Fill::importGradientFill( const AttributeList& rAttribs )
1734 mxGradientModel.reset( new GradientFillModel );
1735 mxGradientModel->mnType = rAttribs.getToken( XML_type, XML_linear );
1736 mxGradientModel->mfAngle = rAttribs.getDouble( XML_degree, 0.0 );
1737 mxGradientModel->mfLeft = rAttribs.getDouble( XML_left, 0.0 );
1738 mxGradientModel->mfRight = rAttribs.getDouble( XML_right, 0.0 );
1739 mxGradientModel->mfTop = rAttribs.getDouble( XML_top, 0.0 );
1740 mxGradientModel->mfBottom = rAttribs.getDouble( XML_bottom, 0.0 );
1743 void Fill::importColor( const AttributeList& rAttribs, double fPosition )
1745 OSL_ENSURE( mxGradientModel.get(), "Fill::importColor - missing gradient data" );
1746 if( mxGradientModel.get() && (fPosition >= 0.0) )
1747 mxGradientModel->maColors[ fPosition ].importColor( rAttribs );
1750 void Fill::importFill( SequenceInputStream& rStrm )
1752 SAL_WARN_IF( mbDxf, "sc", "Fill::importFill - unexpected conditional formatting flag" );
1753 sal_Int32 nPattern = rStrm.readInt32();
1754 if( nPattern == BIFF12_FILL_GRADIENT )
1756 mxGradientModel.reset( new GradientFillModel );
1757 sal_Int32 nStopCount;
1758 rStrm.skip( 16 );
1759 mxGradientModel->readGradient( rStrm );
1760 nStopCount = rStrm.readInt32();
1761 for( sal_Int32 nStop = 0; (nStop < nStopCount) && !rStrm.isEof(); ++nStop )
1762 mxGradientModel->readGradientStop( rStrm, false );
1764 else
1766 mxPatternModel.reset( new PatternFillModel( mbDxf ) );
1767 mxPatternModel->setBiffPattern( nPattern );
1768 rStrm >> mxPatternModel->maPatternColor >> mxPatternModel->maFillColor;
1772 void Fill::importDxfPattern( SequenceInputStream& rStrm )
1774 SAL_WARN_IF( !mbDxf, "sc", "Fill::importDxfPattern - missing conditional formatting flag" );
1775 if( !mxPatternModel )
1776 mxPatternModel.reset( new PatternFillModel( mbDxf ) );
1777 mxPatternModel->setBiffPattern( rStrm.readuInt8() );
1778 mxPatternModel->mbPatternUsed = true;
1781 void Fill::importDxfFgColor( SequenceInputStream& rStrm )
1783 SAL_WARN_IF( !mbDxf, "sc", "Fill::importDxfFgColor - missing conditional formatting flag" );
1784 if( !mxPatternModel )
1785 mxPatternModel.reset( new PatternFillModel( mbDxf ) );
1786 mxPatternModel->maPatternColor.importColor( rStrm );
1787 mxPatternModel->mbPattColorUsed = true;
1790 void Fill::importDxfBgColor( SequenceInputStream& rStrm )
1792 SAL_WARN_IF( !mbDxf, "sc", "Fill::importDxfBgColor - missing conditional formatting flag" );
1793 if( !mxPatternModel )
1794 mxPatternModel.reset( new PatternFillModel( mbDxf ) );
1795 mxPatternModel->maFillColor.importColor( rStrm );
1796 mxPatternModel->mbFillColorUsed = true;
1799 void Fill::importDxfGradient( SequenceInputStream& rStrm )
1801 SAL_WARN_IF( !mbDxf, "sc", "Fill::importDxfGradient - missing conditional formatting flag" );
1802 if( !mxGradientModel )
1803 mxGradientModel.reset( new GradientFillModel );
1804 mxGradientModel->readGradient( rStrm );
1807 void Fill::importDxfStop( SequenceInputStream& rStrm )
1809 SAL_WARN_IF( !mbDxf, "sc", "Fill::importDxfStop - missing conditional formatting flag" );
1810 if( !mxGradientModel )
1811 mxGradientModel.reset( new GradientFillModel );
1812 mxGradientModel->readGradientStop( rStrm, true );
1815 void Fill::finalizeImport()
1817 const GraphicHelper& rGraphicHelper = getBaseFilter().getGraphicHelper();
1819 if( mxPatternModel.get() )
1821 // finalize the OOXML data struct
1822 PatternFillModel& rModel = *mxPatternModel;
1823 if( mbDxf )
1825 if( rModel.mbFillColorUsed && (!rModel.mbPatternUsed || (rModel.mnPattern == XML_solid)) )
1827 rModel.maPatternColor = rModel.maFillColor;
1828 rModel.mnPattern = XML_solid;
1829 rModel.mbPattColorUsed = rModel.mbPatternUsed = true;
1831 else if( !rModel.mbFillColorUsed && rModel.mbPatternUsed && (rModel.mnPattern == XML_solid) )
1833 rModel.mbPatternUsed = false;
1837 // convert to API fill settings
1838 maApiData.mbUsed = rModel.mbPatternUsed;
1839 if( rModel.mnPattern == XML_none )
1841 maApiData.mnColor = API_RGB_TRANSPARENT;
1842 maApiData.mbTransparent = true;
1844 else
1846 sal_Int32 nAlpha = 0x80;
1847 switch( rModel.mnPattern )
1849 case XML_darkDown: nAlpha = 0x40; break;
1850 case XML_darkGray: nAlpha = 0x60; break;
1851 case XML_darkGrid: nAlpha = 0x40; break;
1852 case XML_darkHorizontal: nAlpha = 0x40; break;
1853 case XML_darkTrellis: nAlpha = 0x60; break;
1854 case XML_darkUp: nAlpha = 0x40; break;
1855 case XML_darkVertical: nAlpha = 0x40; break;
1856 case XML_gray0625: nAlpha = 0x08; break;
1857 case XML_gray125: nAlpha = 0x10; break;
1858 case XML_lightDown: nAlpha = 0x20; break;
1859 case XML_lightGray: nAlpha = 0x20; break;
1860 case XML_lightGrid: nAlpha = 0x38; break;
1861 case XML_lightHorizontal: nAlpha = 0x20; break;
1862 case XML_lightTrellis: nAlpha = 0x30; break;
1863 case XML_lightUp: nAlpha = 0x20; break;
1864 case XML_lightVertical: nAlpha = 0x20; break;
1865 case XML_mediumGray: nAlpha = 0x40; break;
1866 case XML_solid: nAlpha = 0x80; break;
1869 ::Color nWinTextColor = rGraphicHelper.getSystemColor( XML_windowText );
1870 ::Color nWinColor = rGraphicHelper.getSystemColor( XML_window );
1872 if( !rModel.mbPattColorUsed )
1873 rModel.maPatternColor.setAuto();
1874 ::Color nPattColor = rModel.maPatternColor.getColor( rGraphicHelper, nWinTextColor );
1876 if( !rModel.mbFillColorUsed )
1877 rModel.maFillColor.setAuto();
1878 ::Color nFillColor = rModel.maFillColor.getColor( rGraphicHelper, nWinColor );
1880 maApiData.mnColor = lclGetMixedColor( nPattColor, nFillColor, nAlpha );
1881 maApiData.mbTransparent = false;
1884 else if( mxGradientModel.get() && !mxGradientModel->maColors.empty() )
1886 GradientFillModel& rModel = *mxGradientModel;
1887 maApiData.mbUsed = true; // no support for differential attributes
1888 GradientFillModel::ColorMap::const_iterator aIt = rModel.maColors.begin();
1889 OSL_ENSURE( !aIt->second.isAuto(), "Fill::finalizeImport - automatic gradient color" );
1890 maApiData.mnColor = aIt->second.getColor( rGraphicHelper, API_RGB_WHITE );
1891 if( ++aIt != rModel.maColors.end() )
1893 OSL_ENSURE( !aIt->second.isAuto(), "Fill::finalizeImport - automatic gradient color" );
1894 ::Color nEndColor = aIt->second.getColor( rGraphicHelper, API_RGB_WHITE );
1895 maApiData.mnColor = lclGetMixedColor( maApiData.mnColor, nEndColor, 0x40 );
1896 maApiData.mbTransparent = false;
1901 void Fill::fillToItemSet( SfxItemSet& rItemSet, bool bSkipPoolDefs ) const
1903 if( maApiData.mbUsed )
1905 SvxBrushItem aBrushItem( ATTR_BACKGROUND );
1906 if ( maApiData.mbTransparent )
1908 aBrushItem.SetColor( COL_TRANSPARENT );
1910 else
1912 aBrushItem.SetColor( maApiData.mnColor );
1914 ScfTools::PutItem( rItemSet, aBrushItem, bSkipPoolDefs );
1918 XfModel::XfModel() :
1919 mnStyleXfId( -1 ),
1920 mnFontId( -1 ),
1921 mnNumFmtId( -1 ),
1922 mnBorderId( -1 ),
1923 mnFillId( -1 ),
1924 mbCellXf( true ),
1925 mbFontUsed( false ),
1926 mbNumFmtUsed( false ),
1927 mbAlignUsed( false ),
1928 mbProtUsed( false ),
1929 mbBorderUsed( false ),
1930 mbAreaUsed( false )
1934 Xf::AttrList::AttrList(const ScPatternAttr* pDefPattern):
1935 mbLatinNumFmtOnly(true),
1936 mpDefPattern(pDefPattern)
1939 Xf::Xf( const WorkbookHelper& rHelper ) :
1940 WorkbookHelper( rHelper ),
1941 mnScNumFmt(0),
1942 maAlignment( rHelper ),
1943 maProtection( rHelper ),
1944 meRotationRef( css::table::CellVertJustify2::STANDARD ),
1945 mpStyleSheet( nullptr )
1949 void Xf::importXf( const AttributeList& rAttribs, bool bCellXf )
1951 maModel.mbCellXf = bCellXf;
1952 // tdf#70565 Set proper default value to "0" of xfId attribute
1953 // When xfId is not exist during .xlsx import
1954 // it must have values set to "0".
1955 // This doesn't impact spreadsheets created with MS Excel,
1956 // as xfId attribute is always created during export to .xlsx
1957 // Not setting "0" value is causing wrong .xlsx import by LibreOffice,
1958 // for spreadsheets created by external applications (ex. SAP BI).
1959 if ( maModel.mbCellXf )
1961 maModel.mnStyleXfId = rAttribs.getInteger( XML_xfId, 0 );
1963 else
1965 maModel.mnStyleXfId = rAttribs.getInteger( XML_xfId, -1 );
1967 maModel.mnFontId = rAttribs.getInteger( XML_fontId, -1 );
1968 maModel.mnNumFmtId = rAttribs.getInteger( XML_numFmtId, -1 );
1969 maModel.mnBorderId = rAttribs.getInteger( XML_borderId, -1 );
1970 maModel.mnFillId = rAttribs.getInteger( XML_fillId, -1 );
1973 /* Default value of the apply*** attributes is dependent on context:
1974 true in cellStyleXfs element, false in cellXfs element... */
1975 maModel.mbAlignUsed = rAttribs.getBool( XML_applyAlignment, !maModel.mbCellXf );
1976 maModel.mbProtUsed = rAttribs.getBool( XML_applyProtection, !maModel.mbCellXf );
1977 maModel.mbFontUsed = rAttribs.getBool( XML_applyFont, !maModel.mbCellXf );
1978 maModel.mbNumFmtUsed = rAttribs.getBool( XML_applyNumberFormat, !maModel.mbCellXf );
1979 maModel.mbBorderUsed = rAttribs.getBool( XML_applyBorder, !maModel.mbCellXf );
1980 maModel.mbAreaUsed = rAttribs.getBool( XML_applyFill, !maModel.mbCellXf );
1983 void Xf::importAlignment( const AttributeList& rAttribs )
1985 maAlignment.importAlignment( rAttribs );
1988 void Xf::importProtection( const AttributeList& rAttribs )
1990 maProtection.importProtection( rAttribs );
1993 void Xf::importXf( SequenceInputStream& rStrm, bool bCellXf )
1995 maModel.mbCellXf = bCellXf;
1996 maModel.mnStyleXfId = rStrm.readuInt16();
1997 maModel.mnNumFmtId = rStrm.readuInt16();
1998 maModel.mnFontId = rStrm.readuInt16();
1999 maModel.mnFillId = rStrm.readuInt16();
2000 maModel.mnBorderId = rStrm.readuInt16();
2001 sal_uInt32 nFlags = rStrm.readuInt32();
2002 maAlignment.setBiff12Data( nFlags );
2003 maProtection.setBiff12Data( nFlags );
2004 // used flags, see comments in Xf::setBiffUsedFlags()
2005 sal_uInt16 nUsedFlags = rStrm.readuInt16();
2006 maModel.mbFontUsed = maModel.mbCellXf == getFlag( nUsedFlags, BIFF12_XF_FONT_USED );
2007 maModel.mbNumFmtUsed = maModel.mbCellXf == getFlag( nUsedFlags, BIFF12_XF_NUMFMT_USED );
2008 maModel.mbAlignUsed = maModel.mbCellXf == getFlag( nUsedFlags, BIFF12_XF_ALIGN_USED );
2009 maModel.mbProtUsed = maModel.mbCellXf == getFlag( nUsedFlags, BIFF12_XF_PROT_USED );
2010 maModel.mbBorderUsed = maModel.mbCellXf == getFlag( nUsedFlags, BIFF12_XF_BORDER_USED );
2011 maModel.mbAreaUsed = maModel.mbCellXf == getFlag( nUsedFlags, BIFF12_XF_AREA_USED );
2014 void Xf::finalizeImport()
2016 // alignment and protection
2017 maAlignment.finalizeImport();
2018 maProtection.finalizeImport();
2021 FontRef Xf::getFont() const
2023 return getStyles().getFont( maModel.mnFontId );
2026 void Xf::applyPatternToAttrList( AttrList& rAttrs, SCROW nRow1, SCROW nRow2, sal_Int32 nNumFmtId )
2028 createPattern();
2029 ScPatternAttr& rPat = *mpPattern;
2030 ScDocument& rDoc = getScDocument();
2031 if ( isCellXf() )
2033 StylesBuffer& rStyles = getStyles();
2034 rStyles.createCellStyle( maModel.mnStyleXfId );
2036 mpStyleSheet = rStyles.getCellStyleSheet( maModel.mnStyleXfId );
2037 if ( mpStyleSheet )
2039 //rDoc.ApplySelectionStyle( static_cast<ScStyleSheet&>(*mpStyleSheet), rMarkData );
2040 rPat.SetStyleSheet(mpStyleSheet, false);
2042 else
2044 ScStyleSheetPool* pStylePool = rDoc.GetStyleSheetPool();
2045 if (pStylePool)
2047 ScStyleSheet* pStyleSheet = static_cast<ScStyleSheet*>(
2048 pStylePool->Find(
2049 ScResId(STR_STYLENAME_STANDARD), SfxStyleFamily::Para));
2051 if (pStyleSheet)
2052 rPat.SetStyleSheet( pStyleSheet, false );
2056 if ( nNumFmtId >= 0 )
2058 ScPatternAttr aNumPat(rDoc.GetPool());
2059 mnScNumFmt = getStyles().writeNumFmtToItemSet( aNumPat.GetItemSet(), nNumFmtId, false );
2060 rPat.GetItemSet().Put(aNumPat.GetItemSet());
2063 if (!sc::NumFmtUtil::isLatinScript(mnScNumFmt, rDoc))
2064 rAttrs.mbLatinNumFmtOnly = false;
2066 if (rPat.GetStyleName())
2068 // Check for a gap between the last entry and this one.
2069 bool bHasGap = false;
2070 if (rAttrs.maAttrs.empty() && nRow1 > 0)
2071 // First attribute range doesn't start at row 0.
2072 bHasGap = true;
2074 if (!rAttrs.maAttrs.empty() && rAttrs.maAttrs.back().nEndRow + 1 < nRow1)
2075 bHasGap = true;
2077 if (bHasGap)
2079 // Fill this gap with the default pattern.
2080 ScAttrEntry aEntry;
2081 aEntry.nEndRow = nRow1 - 1;
2082 aEntry.pPattern = &rDoc.GetPool()->Put(*rAttrs.mpDefPattern);
2083 rAttrs.maAttrs.push_back(aEntry);
2085 // Check if the default pattern is 'General'.
2086 if (!sc::NumFmtUtil::isLatinScript(*aEntry.pPattern, rDoc))
2087 rAttrs.mbLatinNumFmtOnly = false;
2090 ScAttrEntry aEntry;
2091 aEntry.nEndRow = nRow2;
2092 aEntry.pPattern = &rDoc.GetPool()->Put(rPat);
2093 rAttrs.maAttrs.push_back(aEntry);
2095 if (!sc::NumFmtUtil::isLatinScript(*aEntry.pPattern, rDoc))
2096 rAttrs.mbLatinNumFmtOnly = false;
2100 void Xf::writeToDoc( ScDocumentImport& rDoc, const ScRange& rRange )
2102 const StylesBuffer& rStyles = getStyles();
2104 if (isCellXf())
2106 // Cell style name.
2107 OUString aStyleName = rStyles.createCellStyle(maModel.mnStyleXfId);
2109 ScStyleSheet* pStyleSheet =
2110 static_cast<ScStyleSheet*>(
2111 rDoc.getDoc().GetStyleSheetPool()->Find(aStyleName, SfxStyleFamily::Para));
2113 if (pStyleSheet)
2115 rDoc.getDoc().ApplyStyleAreaTab(
2116 rRange.aStart.Col(), rRange.aStart.Row(), rRange.aEnd.Col(), rRange.aEnd.Row(), rRange.aStart.Tab(),
2117 *pStyleSheet);
2121 const ScPatternAttr& rAttr = createPattern();
2122 rDoc.getDoc().ApplyPatternAreaTab(
2123 rRange.aStart.Col(), rRange.aStart.Row(), rRange.aEnd.Col(), rRange.aEnd.Row(), rRange.aStart.Tab(), rAttr);
2126 const ::ScPatternAttr&
2127 Xf::createPattern( bool bSkipPoolDefs )
2129 if( mpPattern.get() )
2130 return *mpPattern;
2131 mpPattern.reset( new ::ScPatternAttr( getScDocument().GetPool() ) );
2132 SfxItemSet& rItemSet = mpPattern->GetItemSet();
2133 /* Enables the used flags, if the formatting attributes differ from the
2134 style XF. In cell XFs Excel uses the cell attributes, if they differ
2135 from the parent style XF (even if the used flag is switched off).
2136 #109899# ...or if the respective flag is not set in parent style XF.
2138 StylesBuffer& rStyles = getStyles();
2140 const Xf* pStyleXf = isCellXf() ? rStyles.getStyleXf( maModel.mnStyleXfId ).get() : nullptr;
2141 if( pStyleXf && !mpStyleSheet )
2143 rStyles.createCellStyle( maModel.mnStyleXfId );
2144 mpStyleSheet = rStyles.getCellStyleSheet( maModel.mnStyleXfId );
2145 OSL_ENSURE( mpStyleSheet, "Xf::createPattern - no parentStyle created" );
2147 const XfModel& rStyleData = pStyleXf->maModel;
2148 if( !maModel.mbFontUsed )
2149 maModel.mbFontUsed = !rStyleData.mbFontUsed || (maModel.mnFontId != rStyleData.mnFontId);
2150 if( !maModel.mbNumFmtUsed )
2151 maModel.mbNumFmtUsed = !rStyleData.mbNumFmtUsed || (maModel.mnNumFmtId != rStyleData.mnNumFmtId);
2152 if( !maModel.mbAlignUsed )
2153 maModel.mbAlignUsed = !rStyleData.mbAlignUsed || !(maAlignment.getApiData() == pStyleXf->maAlignment.getApiData());
2154 if( !maModel.mbProtUsed )
2155 maModel.mbProtUsed = !rStyleData.mbProtUsed || !(maProtection.getApiData() == pStyleXf->maProtection.getApiData());
2156 if( !maModel.mbBorderUsed )
2157 maModel.mbBorderUsed = !rStyleData.mbBorderUsed || !StylesBuffer::equalBorders( maModel.mnBorderId, rStyleData.mnBorderId );
2158 if( !maModel.mbAreaUsed )
2159 maModel.mbAreaUsed = !rStyleData.mbAreaUsed || !StylesBuffer::equalFills( maModel.mnFillId, rStyleData.mnFillId );
2161 // cell protection
2162 if( maModel.mbProtUsed )
2164 maProtection.fillToItemSet( rItemSet, bSkipPoolDefs );
2167 // font
2168 if( maModel.mbFontUsed )
2170 rStyles.writeFontToItemSet( rItemSet, maModel.mnFontId, bSkipPoolDefs );
2173 // value format
2174 if( maModel.mbNumFmtUsed )
2176 mnScNumFmt = rStyles.writeNumFmtToItemSet( rItemSet, maModel.mnNumFmtId, bSkipPoolDefs );
2178 // alignment
2179 if( maModel.mbAlignUsed )
2181 maAlignment.fillToItemSet( rItemSet, bSkipPoolDefs );
2184 // border
2185 if( maModel.mbBorderUsed )
2187 rStyles.writeBorderToItemSet( rItemSet, maModel.mnBorderId, bSkipPoolDefs );
2190 // area
2191 if( maModel.mbAreaUsed )
2193 rStyles.writeFillToItemSet( rItemSet, maModel.mnFillId, bSkipPoolDefs );
2196 /* #i38709# Decide which rotation reference mode to use. If any outer
2197 border line of the cell is set (either explicitly or via cell style),
2198 and the cell contents are rotated, set rotation reference to bottom of
2199 cell. This causes the borders to be painted rotated with the text. */
2200 if( const Alignment* pAlignment = maModel.mbAlignUsed ? &maAlignment : (pStyleXf ? &pStyleXf->maAlignment : nullptr) )
2202 SvxRotateMode eRotateMode = SVX_ROTATE_MODE_STANDARD;
2203 sal_Int32 nBorderId = maModel.mbBorderUsed ? maModel.mnBorderId : (pStyleXf ? pStyleXf->maModel.mnBorderId : -1);
2204 if( const Border* pBorder = rStyles.getBorder( nBorderId ).get() )
2206 if( (pAlignment->getApiData().mnRotation != 0) && pBorder->getApiData().hasAnyOuterBorder() )
2208 meRotationRef = css::table::CellVertJustify2::BOTTOM;
2209 eRotateMode = SVX_ROTATE_MODE_BOTTOM;
2212 ScfTools::PutItem( rItemSet, SvxRotateModeItem( eRotateMode, ATTR_ROTATE_MODE ), bSkipPoolDefs );
2215 return *mpPattern;
2218 Dxf::Dxf( const WorkbookHelper& rHelper ) :
2219 WorkbookHelper( rHelper )
2223 FontRef const & Dxf::createFont( bool bAlwaysNew )
2225 if( bAlwaysNew || !mxFont )
2226 mxFont.reset( new Font( *this, true ) );
2227 return mxFont;
2230 BorderRef const & Dxf::createBorder( bool bAlwaysNew )
2232 if( bAlwaysNew || !mxBorder )
2233 mxBorder.reset( new Border( *this, true ) );
2234 return mxBorder;
2237 FillRef const & Dxf::createFill( bool bAlwaysNew )
2239 if( bAlwaysNew || !mxFill )
2240 mxFill.reset( new Fill( *this, true ) );
2241 return mxFill;
2244 void Dxf::importNumFmt( const AttributeList& rAttribs )
2246 // don't propagate number formats defined in Dxf entries
2247 // they can have the same id ( but different format codes ) as those
2248 // defined globally earlier. We discard the id defined in XML_numFmtId
2249 // and generate one ourselves ( this assumes that the normal numberformat
2250 // import has already taken place )
2251 sal_Int32 nNumFmtId = getStyles().nextFreeNumFmtId();
2252 OUString aFmtCode = rAttribs.getXString( XML_formatCode, OUString() );
2253 mxNumFmt = getStyles().createNumFmt( nNumFmtId, aFmtCode );
2256 void Dxf::importDxf( SequenceInputStream& rStrm )
2258 sal_Int32 nNumFmtId = -1;
2259 OUString aFmtCode;
2260 sal_uInt16 nRecCount;
2261 rStrm.skip( 4 ); // flags
2262 nRecCount = rStrm.readuInt16();
2263 for( sal_uInt16 nRec = 0; !rStrm.isEof() && (nRec < nRecCount); ++nRec )
2265 sal_uInt16 nSubRecId, nSubRecSize;
2266 sal_Int64 nRecEnd = rStrm.tell();
2267 nSubRecId = rStrm.readuInt16();
2268 nSubRecSize = rStrm.readuInt16();
2269 nRecEnd += nSubRecSize;
2270 switch( nSubRecId )
2272 case BIFF12_DXF_FILL_PATTERN: createFill( false )->importDxfPattern( rStrm ); break;
2273 case BIFF12_DXF_FILL_FGCOLOR: createFill( false )->importDxfFgColor( rStrm ); break;
2274 case BIFF12_DXF_FILL_BGCOLOR: createFill( false )->importDxfBgColor( rStrm ); break;
2275 case BIFF12_DXF_FILL_GRADIENT: createFill( false )->importDxfGradient( rStrm ); break;
2276 case BIFF12_DXF_FILL_STOP: createFill( false )->importDxfStop( rStrm ); break;
2277 case BIFF12_DXF_FONT_COLOR: createFont( false )->importDxfColor( rStrm ); break;
2278 case BIFF12_DXF_BORDER_TOP: createBorder( false )->importDxfBorder( XLS_TOKEN( top ), rStrm ); break;
2279 case BIFF12_DXF_BORDER_BOTTOM: createBorder( false )->importDxfBorder( XLS_TOKEN( bottom ), rStrm ); break;
2280 case BIFF12_DXF_BORDER_LEFT: createBorder( false )->importDxfBorder( XLS_TOKEN( left ), rStrm ); break;
2281 case BIFF12_DXF_BORDER_RIGHT: createBorder( false )->importDxfBorder( XLS_TOKEN( right ), rStrm ); break;
2282 case BIFF12_DXF_FONT_NAME: createFont( false )->importDxfName( rStrm ); break;
2283 case BIFF12_DXF_FONT_WEIGHT: createFont( false )->importDxfWeight( rStrm ); break;
2284 case BIFF12_DXF_FONT_UNDERLINE: createFont( false )->importDxfUnderline( rStrm ); break;
2285 case BIFF12_DXF_FONT_ESCAPEMENT: createFont( false )->importDxfEscapement( rStrm ); break;
2286 case BIFF12_DXF_FONT_ITALIC: createFont( false )->importDxfFlag( XML_i, rStrm ); break;
2287 case BIFF12_DXF_FONT_STRIKE: createFont( false )->importDxfFlag( XML_strike, rStrm ); break;
2288 case BIFF12_DXF_FONT_OUTLINE: createFont( false )->importDxfFlag( XML_outline, rStrm ); break;
2289 case BIFF12_DXF_FONT_SHADOW: createFont( false )->importDxfFlag( XML_shadow, rStrm ); break;
2290 case BIFF12_DXF_FONT_HEIGHT: createFont( false )->importDxfHeight( rStrm ); break;
2291 case BIFF12_DXF_FONT_SCHEME: createFont( false )->importDxfScheme( rStrm ); break;
2292 case BIFF12_DXF_NUMFMT_CODE: aFmtCode = BiffHelper::readString( rStrm, false ); break;
2293 case BIFF12_DXF_NUMFMT_ID: nNumFmtId = rStrm.readuInt16(); break;
2295 rStrm.seek( nRecEnd );
2297 OSL_ENSURE( !rStrm.isEof() && (rStrm.getRemaining() == 0), "Dxf::importDxf - unexpected remaining data" );
2298 mxNumFmt = getStyles().createNumFmt( nNumFmtId, aFmtCode );
2301 void Dxf::finalizeImport()
2303 if( mxFont.get() )
2304 mxFont->finalizeImport();
2305 bool bRTL = false;
2306 // number format already finalized by the number formats buffer
2307 if( mxAlignment.get() )
2309 mxAlignment->finalizeImport();
2310 // how do we detect RTL when text dir is OOX_XF_CONTEXT? ( seems you
2311 // would need access to the cell content, which we don't here )
2312 if ( mxAlignment->getModel().mnTextDir == OOX_XF_TEXTDIR_RTL )
2313 bRTL = true;
2315 if( mxProtection.get() )
2316 mxProtection->finalizeImport();
2317 if( mxBorder.get() )
2319 mxBorder->finalizeImport( bRTL );
2321 if( mxFill.get() )
2322 mxFill->finalizeImport();
2325 void Dxf::fillToItemSet( SfxItemSet& rSet ) const
2327 if (mxFont)
2328 mxFont->fillToItemSet(rSet, false);
2329 if (mxNumFmt)
2330 mxNumFmt->fillToItemSet(rSet);
2331 if (mxAlignment)
2332 mxAlignment->fillToItemSet(rSet);
2333 if (mxProtection)
2334 mxProtection->fillToItemSet(rSet);
2335 if (mxBorder)
2336 mxBorder->fillToItemSet(rSet);
2337 if (mxFill)
2338 mxFill->fillToItemSet(rSet);
2341 namespace {
2343 const sal_Char* const sppcStyleNames[] =
2345 "Normal",
2346 "RowLevel_", // outline level will be appended
2347 "ColLevel_", // outline level will be appended
2348 "Comma",
2349 "Currency",
2350 "Percent",
2351 "Comma [0]", // new in BIFF4
2352 "Currency [0]",
2353 "Hyperlink", // new in BIFF8
2354 "Followed Hyperlink",
2355 "Note", // new in OOX
2356 "Warning Text",
2357 nullptr,
2358 nullptr,
2359 nullptr,
2360 "Title",
2361 "Heading 1",
2362 "Heading 2",
2363 "Heading 3",
2364 "Heading 4",
2365 "Input",
2366 "Output",
2367 "Calculation",
2368 "Check Cell",
2369 "Linked Cell",
2370 "Total",
2371 "Good",
2372 "Bad",
2373 "Neutral",
2374 "Accent1",
2375 "20% - Accent1",
2376 "40% - Accent1",
2377 "60% - Accent1",
2378 "Accent2",
2379 "20% - Accent2",
2380 "40% - Accent2",
2381 "60% - Accent2",
2382 "Accent3",
2383 "20% - Accent3",
2384 "40% - Accent3",
2385 "60% - Accent3",
2386 "Accent4",
2387 "20% - Accent4",
2388 "40% - Accent4",
2389 "60% - Accent4",
2390 "Accent5",
2391 "20% - Accent5",
2392 "40% - Accent5",
2393 "60% - Accent5",
2394 "Accent6",
2395 "20% - Accent6",
2396 "40% - Accent6",
2397 "60% - Accent6",
2398 "Explanatory Text"
2400 const sal_Int32 snStyleNamesCount = static_cast< sal_Int32 >( SAL_N_ELEMENTS( sppcStyleNames ) );
2402 OUString lclGetBuiltinStyleName( sal_Int32 nBuiltinId, const OUString& rName, sal_Int32 nLevel = 0 )
2404 OSL_ENSURE( (0 <= nBuiltinId) && (nBuiltinId < snStyleNamesCount), "lclGetBuiltinStyleName - unknown built-in style" );
2405 OUStringBuffer aStyleName("Excel Built-in ");
2406 if( (0 <= nBuiltinId) && (nBuiltinId < snStyleNamesCount) && (sppcStyleNames[ nBuiltinId ] != nullptr) )
2407 aStyleName.appendAscii( sppcStyleNames[ nBuiltinId ] );
2408 else if( !rName.isEmpty() )
2409 aStyleName.append( rName );
2410 else
2411 aStyleName.append( nBuiltinId );
2412 if( (nBuiltinId == OOX_STYLE_ROWLEVEL) || (nBuiltinId == OOX_STYLE_COLLEVEL) )
2413 aStyleName.append( nLevel );
2414 return aStyleName.makeStringAndClear();
2417 OUString lclCreateStyleName( const CellStyleModel& rModel )
2419 return rModel.mbBuiltin ? lclGetBuiltinStyleName( rModel.mnBuiltinId, rModel.maName, rModel.mnLevel ) : rModel.maName;
2422 } // namespace
2424 CellStyleModel::CellStyleModel() :
2425 mnXfId( -1 ),
2426 mnBuiltinId( -1 ),
2427 mnLevel( 0 ),
2428 mbBuiltin( false ),
2429 mbCustom( false ),
2430 mbHidden( false )
2434 bool CellStyleModel::isBuiltin() const
2436 return mbBuiltin && (mnBuiltinId >= 0);
2439 bool CellStyleModel::isDefaultStyle() const
2441 return mbBuiltin && (mnBuiltinId == OOX_STYLE_NORMAL);
2444 CellStyle::CellStyle( const WorkbookHelper& rHelper ) :
2445 WorkbookHelper( rHelper ),
2446 mbCreated( false ),
2447 mpStyleSheet( nullptr )
2451 void CellStyle::importCellStyle( const AttributeList& rAttribs )
2453 maModel.maName = rAttribs.getXString( XML_name, OUString() );
2454 maModel.mnXfId = rAttribs.getInteger( XML_xfId, -1 );
2455 maModel.mnBuiltinId = rAttribs.getInteger( XML_builtinId, -1 );
2456 maModel.mnLevel = rAttribs.getInteger( XML_iLevel, 0 );
2457 maModel.mbBuiltin = rAttribs.hasAttribute( XML_builtinId );
2458 maModel.mbCustom = rAttribs.getBool( XML_customBuiltin, false );
2459 maModel.mbHidden = rAttribs.getBool( XML_hidden, false );
2462 void CellStyle::importCellStyle( SequenceInputStream& rStrm )
2464 sal_uInt16 nFlags;
2465 maModel.mnXfId = rStrm.readInt32();
2466 nFlags = rStrm.readuInt16();
2467 maModel.mnBuiltinId = rStrm.readInt8();
2468 maModel.mnLevel = rStrm.readInt8();
2469 rStrm >> maModel.maName;
2470 maModel.mbBuiltin = getFlag( nFlags, BIFF12_CELLSTYLE_BUILTIN );
2471 maModel.mbCustom = getFlag( nFlags, BIFF12_CELLSTYLE_CUSTOM );
2472 maModel.mbHidden = getFlag( nFlags, BIFF12_CELLSTYLE_HIDDEN );
2475 void CellStyle::createCellStyle()
2478 // #i1624# #i1768# ignore unnamed user styles
2479 bool bDefStyle = maModel.isDefaultStyle();
2480 if( !mbCreated )
2482 if ( bDefStyle && maFinalName.isEmpty() )
2483 maFinalName = ScResId( STR_STYLENAME_STANDARD );
2484 mbCreated = maFinalName.isEmpty();
2487 if( !mbCreated && !mpStyleSheet )
2489 bool bCreatePattern = false;
2490 Xf* pXF = getStyles().getStyleXf( maModel.mnXfId ).get();
2491 ::ScDocument& rDoc = getScDocument();
2493 if( bDefStyle )
2495 // use existing "Default" style sheet
2496 mpStyleSheet = static_cast< ScStyleSheet* >( rDoc.GetStyleSheetPool()->Find(
2497 ScResId( STR_STYLENAME_STANDARD ), SfxStyleFamily::Para ) );
2498 OSL_ENSURE( mpStyleSheet, "CellStyle::createStyle - Default style not found" );
2499 bCreatePattern = true;
2501 else
2503 mpStyleSheet = static_cast< ScStyleSheet* >( rDoc.GetStyleSheetPool()->Find( maFinalName, SfxStyleFamily::Para ) );
2504 if( !mpStyleSheet )
2506 mpStyleSheet = &static_cast< ScStyleSheet& >( rDoc.GetStyleSheetPool()->Make( maFinalName, SfxStyleFamily::Para, SfxStyleSearchBits::UserDefined ) );
2507 bCreatePattern = true;
2511 // bDefStyle==true omits default pool items in CreatePattern()
2512 if( bCreatePattern && mpStyleSheet && pXF )
2513 mpStyleSheet->GetItemSet().Put( pXF->createPattern( bDefStyle ).GetItemSet() );
2517 void CellStyle::finalizeImport( const OUString& rFinalName )
2519 maFinalName = rFinalName;
2520 if( !maModel.isBuiltin() || maModel.mbCustom )
2521 createCellStyle();
2524 CellStyleBuffer::CellStyleBuffer( const WorkbookHelper& rHelper ) :
2525 WorkbookHelper( rHelper )
2529 CellStyleRef CellStyleBuffer::importCellStyle( const AttributeList& rAttribs )
2531 CellStyleRef xCellStyle( new CellStyle( *this ) );
2532 xCellStyle->importCellStyle( rAttribs );
2533 insertCellStyle( xCellStyle );
2534 return xCellStyle;
2537 CellStyleRef CellStyleBuffer::importCellStyle( SequenceInputStream& rStrm )
2539 CellStyleRef xCellStyle( new CellStyle( *this ) );
2540 xCellStyle->importCellStyle( rStrm );
2541 insertCellStyle( xCellStyle );
2542 return xCellStyle;
2545 void CellStyleBuffer::finalizeImport()
2547 // calculate final names of all styles
2548 typedef RefMap< OUString, CellStyle, IgnoreCaseCompare > CellStyleNameMap;
2549 CellStyleNameMap aCellStyles;
2550 CellStyleVector aConflictNameStyles;
2552 /* First, reserve style names that are built-in in Calc. This causes that
2553 imported cell styles get different unused names and thus do not try to
2554 overwrite these built-in styles. */
2557 // unfortunately, com.sun.star.style.StyleFamily does not implement XEnumerationAccess...
2558 Reference< XIndexAccess > xStyleFamilyIA( getCellStyleFamily(), UNO_QUERY_THROW );
2559 for( sal_Int32 nIndex = 0, nCount = xStyleFamilyIA->getCount(); nIndex < nCount; ++nIndex )
2561 Reference< XStyle > xStyle( xStyleFamilyIA->getByIndex( nIndex ), UNO_QUERY_THROW );
2562 if( !xStyle->isUserDefined() )
2564 // create an empty entry by using ::std::map<>::operator[]
2565 aCellStyles[ xStyle->getName() ];
2569 catch( Exception& )
2573 /* Calculate names of built-in styles. Store styles with reserved names
2574 in the aConflictNameStyles list. */
2575 for( const auto& rxStyle : maBuiltinStyles )
2577 const CellStyleModel& rModel = rxStyle->getModel();
2578 if (rModel.isDefaultStyle())
2579 continue;
2581 OUString aStyleName = lclCreateStyleName( rModel );
2582 /* If a builtin style entry already exists,
2583 we just stick with the last definition and ignore
2584 the preceding ones. */
2585 aCellStyles[ aStyleName ] = rxStyle;
2588 /* Calculate names of user defined styles. Store styles with reserved
2589 names in the aConflictNameStyles list. */
2590 for( const auto& rxStyle : maUserStyles )
2592 const CellStyleModel& rModel = rxStyle->getModel();
2593 OUString aStyleName = lclCreateStyleName( rModel );
2594 // #i1624# #i1768# ignore unnamed user styles
2595 if( aStyleName.getLength() > 0 )
2597 if( aCellStyles.find( aStyleName ) != aCellStyles.end() )
2598 aConflictNameStyles.push_back( rxStyle );
2599 else
2600 aCellStyles[ aStyleName ] = rxStyle;
2604 // find unused names for all styles with conflicting names
2605 // having the index counter outside the loop prevents performance problems with opening some pathological documents (tdf#62095)
2606 sal_Int32 nIndex = 0;
2607 for( const auto& rxStyle : aConflictNameStyles )
2609 const CellStyleModel& rModel = rxStyle->getModel();
2610 OUString aStyleName = lclCreateStyleName( rModel );
2611 OUString aUnusedName;
2614 aUnusedName = aStyleName + OUStringChar(' ') + OUString::number( ++nIndex );
2616 while( aCellStyles.find( aUnusedName ) != aCellStyles.end() );
2617 aCellStyles[ aUnusedName ] = rxStyle;
2620 // set final names and create user-defined and modified built-in cell styles
2621 aCellStyles.forEachMemWithKey( &CellStyle::finalizeImport );
2624 sal_Int32 CellStyleBuffer::getDefaultXfId() const
2626 return mxDefStyle.get() ? mxDefStyle->getModel().mnXfId : -1;
2629 OUString CellStyleBuffer::getDefaultStyleName() const
2631 return createCellStyle( mxDefStyle );
2634 OUString CellStyleBuffer::createCellStyle( sal_Int32 nXfId ) const
2636 return createCellStyle( maStylesByXf.get( nXfId ) );
2639 ::ScStyleSheet* CellStyleBuffer::getCellStyleSheet( sal_Int32 nXfId ) const
2641 return getCellStyleSheet( maStylesByXf.get( nXfId ) );
2644 // private --------------------------------------------------------------------
2646 void CellStyleBuffer::insertCellStyle( CellStyleRef const & xCellStyle )
2648 const CellStyleModel& rModel = xCellStyle->getModel();
2649 if( rModel.mnXfId >= 0 )
2651 // insert into the built-in map or user defined map
2652 (rModel.isBuiltin() ? maBuiltinStyles : maUserStyles).push_back( xCellStyle );
2654 // insert into the XF identifier map
2655 OSL_ENSURE( maStylesByXf.count( rModel.mnXfId ) == 0, "CellStyleBuffer::insertCellStyle - multiple styles with equal XF identifier" );
2656 maStylesByXf[ rModel.mnXfId ] = xCellStyle;
2658 // remember default cell style
2659 if( rModel.isDefaultStyle() )
2660 mxDefStyle = xCellStyle;
2664 ::ScStyleSheet* CellStyleBuffer::getCellStyleSheet( const CellStyleRef& rxCellStyle )
2666 ::ScStyleSheet* pStyleSheet = nullptr;
2667 if ( rxCellStyle.get() )
2668 pStyleSheet = rxCellStyle->getStyleSheet();
2669 return pStyleSheet;
2672 OUString CellStyleBuffer::createCellStyle( const CellStyleRef& rxCellStyle )
2674 if( rxCellStyle.get() )
2676 rxCellStyle->createCellStyle();
2677 const OUString& rStyleName = rxCellStyle->getFinalStyleName();
2678 if( !rStyleName.isEmpty() )
2679 return rStyleName;
2681 // on error: fallback to default style
2682 return lclGetBuiltinStyleName( OOX_STYLE_NORMAL, OUString() );
2685 AutoFormatModel::AutoFormatModel() :
2686 mnAutoFormatId( 0 ),
2687 mbApplyNumFmt( false ),
2688 mbApplyFont( false ),
2689 mbApplyAlignment( false ),
2690 mbApplyBorder( false ),
2691 mbApplyFill( false ),
2692 mbApplyProtection( false )
2696 StylesBuffer::StylesBuffer( const WorkbookHelper& rHelper ) :
2697 WorkbookHelper( rHelper ),
2698 maPalette( rHelper ),
2699 maNumFmts( rHelper ),
2700 maCellStyles( rHelper )
2704 FontRef StylesBuffer::createFont()
2706 FontRef xFont( new Font( *this, false ) );
2707 maFonts.push_back( xFont );
2708 return xFont;
2711 NumberFormatRef StylesBuffer::createNumFmt( sal_Int32 nNumFmtId, const OUString& rFmtCode )
2713 return maNumFmts.createNumFmt( nNumFmtId, rFmtCode );
2716 sal_Int32 StylesBuffer::nextFreeNumFmtId()
2718 return maNumFmts.nextFreeId();
2721 BorderRef StylesBuffer::createBorder()
2723 BorderRef xBorder( new Border( *this, false ) );
2724 maBorders.push_back( xBorder );
2725 return xBorder;
2728 FillRef StylesBuffer::createFill()
2730 FillRef xFill( new Fill( *this, false ) );
2731 maFills.push_back( xFill );
2732 return xFill;
2735 XfRef StylesBuffer::createCellXf()
2737 XfRef xXf( new Xf( *this ) );
2738 maCellXfs.push_back( xXf );
2739 return xXf;
2742 XfRef StylesBuffer::createStyleXf()
2744 XfRef xXf( new Xf( *this ) );
2745 maStyleXfs.push_back( xXf );
2746 return xXf;
2749 DxfRef StylesBuffer::createDxf()
2751 DxfRef xDxf( new Dxf( *this ) );
2752 maDxfs.push_back( xDxf );
2753 return xDxf;
2756 DxfRef StylesBuffer::createExtDxf()
2758 DxfRef xDxf( new Dxf( *this ) );
2759 maExtDxfs.push_back( xDxf );
2760 return xDxf;
2763 void StylesBuffer::importPaletteColor( const AttributeList& rAttribs )
2765 maPalette.importPaletteColor( rAttribs );
2768 NumberFormatRef StylesBuffer::importNumFmt( const AttributeList& rAttribs )
2770 return maNumFmts.importNumFmt( rAttribs );
2773 CellStyleRef StylesBuffer::importCellStyle( const AttributeList& rAttribs )
2775 return maCellStyles.importCellStyle( rAttribs );
2778 void StylesBuffer::importPaletteColor( SequenceInputStream& rStrm )
2780 maPalette.importPaletteColor( rStrm );
2783 void StylesBuffer::importNumFmt( SequenceInputStream& rStrm )
2785 maNumFmts.importNumFmt( rStrm );
2788 void StylesBuffer::importCellStyle( SequenceInputStream& rStrm )
2790 maCellStyles.importCellStyle( rStrm );
2793 void StylesBuffer::finalizeImport()
2795 // fonts first, are needed to finalize unit converter and XFs below
2796 maFonts.forEachMem( &Font::finalizeImport );
2797 // finalize unit coefficients after default font is known
2798 getUnitConverter().finalizeImport();
2799 // number formats
2800 maNumFmts.finalizeImport();
2801 // borders and fills
2802 // is there a document wide RTL setting that we
2803 // would/could need to pass to finalizeImport here ?
2804 maBorders.forEachMem( &Border::finalizeImport, false );
2805 maFills.forEachMem( &Fill::finalizeImport );
2806 // style XFs and cell XFs
2807 maStyleXfs.forEachMem( &Xf::finalizeImport );
2808 maCellXfs.forEachMem( &Xf::finalizeImport );
2809 // built-in and user defined cell styles
2810 maCellStyles.finalizeImport();
2811 // differential formatting (for conditional formatting)
2812 maDxfs.forEachMem( &Dxf::finalizeImport );
2815 ::Color StylesBuffer::getPaletteColor( sal_Int32 nPaletteIdx ) const
2817 return maPalette.getColor( nPaletteIdx );
2820 FontRef StylesBuffer::getFont( sal_Int32 nFontId ) const
2822 return maFonts.get( nFontId );
2825 BorderRef StylesBuffer::getBorder( sal_Int32 nBorderId ) const
2827 return maBorders.get( nBorderId );
2830 XfRef StylesBuffer::getCellXf( sal_Int32 nXfId ) const
2832 return maCellXfs.get( nXfId );
2835 XfRef StylesBuffer::getStyleXf( sal_Int32 nXfId ) const
2837 return maStyleXfs.get( nXfId );
2840 FontRef StylesBuffer::getFontFromCellXf( sal_Int32 nXfId ) const
2842 FontRef xFont;
2843 if( const Xf* pXf = getCellXf( nXfId ).get() )
2844 xFont = pXf->getFont();
2845 return xFont;
2848 FontRef StylesBuffer::getDefaultFont() const
2850 FontRef xDefFont;
2851 if( const Xf* pXf = getStyleXf( maCellStyles.getDefaultXfId() ).get() )
2852 xDefFont = pXf->getFont();
2853 // no font from styles - try first loaded font (e.g. BIFF2)
2854 if( !xDefFont )
2855 xDefFont = maFonts.get( 0 );
2856 OSL_ENSURE( xDefFont.get(), "StylesBuffer::getDefaultFont - no default font found" );
2857 return xDefFont;
2860 const FontModel& StylesBuffer::getDefaultFontModel() const
2862 FontRef xDefFont = getDefaultFont();
2863 return xDefFont.get() ? xDefFont->getModel() : getTheme().getDefaultFontModel();
2866 bool StylesBuffer::equalBorders( sal_Int32 nBorderId1, sal_Int32 nBorderId2 )
2868 // in OOXML, borders are assumed to be unique
2869 return nBorderId1 == nBorderId2;
2872 bool StylesBuffer::equalFills( sal_Int32 nFillId1, sal_Int32 nFillId2 )
2874 // in OOXML, fills are assumed to be unique
2875 return nFillId1 == nFillId2;
2878 OUString StylesBuffer::getDefaultStyleName() const
2880 return maCellStyles.getDefaultStyleName();
2883 OUString StylesBuffer::createCellStyle( sal_Int32 nXfId ) const
2885 return maCellStyles.createCellStyle( nXfId );
2888 ::ScStyleSheet* StylesBuffer::getCellStyleSheet( sal_Int32 nXfId ) const
2890 return maCellStyles.getCellStyleSheet( nXfId );
2893 OUString StylesBuffer::createDxfStyle( sal_Int32 nDxfId ) const
2895 OUString& rStyleName = maDxfStyles[ nDxfId ];
2896 if (!rStyleName.isEmpty())
2897 return rStyleName;
2899 if (Dxf* pDxf = maDxfs.get(nDxfId).get())
2901 rStyleName = "ConditionalStyle_" + OUString::number(nDxfId + 1);
2903 // Create a cell style. This may overwrite an existing style if
2904 // one with the same name exists.
2905 ScStyleSheet& rStyleSheet = ScfTools::MakeCellStyleSheet(
2906 *getScDocument().GetStyleSheetPool(), rStyleName, true);
2908 rStyleSheet.ResetParent();
2909 SfxItemSet& rStyleItemSet =
2910 rStyleSheet.GetItemSet();
2912 pDxf->fillToItemSet(rStyleItemSet);
2916 // on error: fallback to default style
2917 if (rStyleName.isEmpty())
2918 rStyleName = maCellStyles.getDefaultStyleName();
2920 return rStyleName;
2923 OUString StylesBuffer::createExtDxfStyle( sal_Int32 nDxfId ) const
2925 OUString rStyleName;
2927 if (Dxf* pDxf = maExtDxfs.get(nDxfId).get())
2929 rStyleName = "ExtConditionalStyle_" + OUString::number(nDxfId + 1);
2931 // Create a cell style. This may overwrite an existing style if
2932 // one with the same name exists.
2933 ScStyleSheet& rStyleSheet = ScfTools::MakeCellStyleSheet(
2934 *getScDocument().GetStyleSheetPool(), rStyleName, true);
2936 rStyleSheet.ResetParent();
2937 SfxItemSet& rStyleItemSet =
2938 rStyleSheet.GetItemSet();
2940 pDxf->fillToItemSet(rStyleItemSet);
2943 // on error: fallback to default style
2944 if (rStyleName.isEmpty())
2945 rStyleName = maCellStyles.getDefaultStyleName();
2947 return rStyleName;
2950 void StylesBuffer::writeFontToItemSet( SfxItemSet& rItemSet, sal_Int32 nFontId, bool bSkipPoolDefs ) const
2952 if( Font* pFont = maFonts.get( nFontId ).get() )
2953 pFont->fillToItemSet( rItemSet, false, bSkipPoolDefs );
2956 sal_uInt32 StylesBuffer::writeNumFmtToItemSet( SfxItemSet& rItemSet, sal_uInt32 nNumFmtId, bool bSkipPoolDefs ) const
2958 return maNumFmts.fillToItemSet( rItemSet, nNumFmtId, bSkipPoolDefs );
2961 void StylesBuffer::writeBorderToItemSet( SfxItemSet& rItemSet, sal_Int32 nBorderId, bool bSkipPoolDefs ) const
2963 if( Border* pBorder = maBorders.get( nBorderId ).get() )
2964 pBorder->fillToItemSet( rItemSet, bSkipPoolDefs );
2967 void StylesBuffer::writeFillToItemSet( SfxItemSet& rItemSet, sal_Int32 nFillId, bool bSkipPoolDefs ) const
2969 if( Fill* pFill = maFills.get( nFillId ).get() )
2970 pFill->fillToItemSet( rItemSet, bSkipPoolDefs );
2973 bool operator==( const XfModel& rXfModel1, const XfModel& rXfModel2 )
2975 return ( rXfModel1.mbCellXf == rXfModel2.mbCellXf &&
2976 rXfModel1.mnStyleXfId == rXfModel2.mnStyleXfId &&
2977 rXfModel1.mbFontUsed == rXfModel2.mbFontUsed &&
2978 rXfModel1.mnFontId == rXfModel2.mnFontId &&
2979 rXfModel1.mbNumFmtUsed == rXfModel2.mbNumFmtUsed &&
2980 rXfModel1.mnNumFmtId == rXfModel2.mnNumFmtId &&
2981 rXfModel1.mbAlignUsed == rXfModel2.mbAlignUsed &&
2982 rXfModel1.mbBorderUsed == rXfModel2.mbBorderUsed &&
2983 rXfModel1.mnBorderId == rXfModel2.mnBorderId &&
2984 rXfModel1.mbAreaUsed == rXfModel2.mbAreaUsed &&
2985 rXfModel1.mnFillId == rXfModel2.mnFillId &&
2986 rXfModel1.mbProtUsed == rXfModel2.mbProtUsed );
2989 bool operator==( const Xf& rXf1, const Xf& rXf2 )
2991 if ( rXf1.maModel == rXf2.maModel )
2993 if ( rXf1.maModel.mbAlignUsed )
2995 if ( !( rXf1.maAlignment.getApiData() == rXf2.maAlignment.getApiData() ) )
2996 return false;
2998 if ( rXf1.maModel.mbProtUsed )
3000 if ( !( rXf1.maProtection.getApiData() == rXf2.maProtection.getApiData() ) )
3001 return false;
3003 return true;
3005 return false;
3008 void StylesBuffer::writeCellXfToDoc(
3009 ScDocumentImport& rDoc, const ScRange& rRange, sal_Int32 nXfId ) const
3011 Xf* pXf = maCellXfs.get(nXfId).get();
3012 if (!pXf)
3013 return;
3015 pXf->writeToDoc(rDoc, rRange);
3018 } // namespace xls
3019 } // namespace oox
3021 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */