1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #include <stylesbuffer.hxx>
21 #include <patterncache.hxx>
23 #include <com/sun/star/awt/FontDescriptor.hpp>
24 #include <com/sun/star/awt/FontFamily.hpp>
25 #include <com/sun/star/awt/FontPitch.hpp>
26 #include <com/sun/star/awt/FontSlant.hpp>
27 #include <com/sun/star/awt/FontStrikeout.hpp>
28 #include <com/sun/star/awt/FontType.hpp>
29 #include <com/sun/star/awt/FontWeight.hpp>
30 #include <com/sun/star/awt/FontUnderline.hpp>
31 #include <com/sun/star/awt/XDevice.hpp>
32 #include <com/sun/star/awt/XFont2.hpp>
33 #include <com/sun/star/container/XIndexAccess.hpp>
34 #include <com/sun/star/sheet/XSpreadsheetDocument.hpp>
35 #include <com/sun/star/style/XStyle.hpp>
36 #include <com/sun/star/text/WritingMode2.hpp>
37 #include <com/sun/star/table/BorderLineStyle.hpp>
38 #include <com/sun/star/table/CellVertJustify2.hpp>
39 #include <com/sun/star/table/CellJustifyMethod.hpp>
40 #include <editeng/justifyitem.hxx>
41 #include <editeng/frmdiritem.hxx>
42 #include <editeng/fontitem.hxx>
43 #include <editeng/postitem.hxx>
44 #include <editeng/fhgtitem.hxx>
45 #include <editeng/wghtitem.hxx>
46 #include <editeng/udlnitem.hxx>
47 #include <editeng/colritem.hxx>
48 #include <editeng/crossedoutitem.hxx>
49 #include <editeng/contouritem.hxx>
50 #include <editeng/escapementitem.hxx>
51 #include <editeng/shdditem.hxx>
52 #include <editeng/eeitem.hxx>
53 #include <editeng/borderline.hxx>
54 #include <editeng/boxitem.hxx>
55 #include <editeng/lineitem.hxx>
56 #include <editeng/brushitem.hxx>
57 #include <svx/rotmodit.hxx>
58 #include <tools/fontenum.hxx>
59 #include <tools/UnitConversion.hxx>
61 #include <vcl/unohelp.hxx>
62 #include <rtl/tencinfo.h>
63 #include <rtl/ustrbuf.hxx>
64 #include <sal/log.hxx>
65 #include <osl/diagnose.h>
66 #include <oox/core/filterbase.hxx>
67 #include <oox/helper/attributelist.hxx>
68 #include <oox/helper/binaryinputstream.hxx>
69 #include <oox/helper/containerhelper.hxx>
70 #include <oox/helper/propertymap.hxx>
71 #include <oox/helper/propertyset.hxx>
72 #include <oox/token/namespaces.hxx>
73 #include <oox/token/properties.hxx>
74 #include <oox/token/tokens.hxx>
75 #include <themebuffer.hxx>
76 #include <unitconverter.hxx>
77 #include <document.hxx>
78 #include <stlpool.hxx>
79 #include <docpool.hxx>
81 #include <scitems.hxx>
83 #include <globstr.hrc>
84 #include <scresid.hxx>
85 #include <documentimport.hxx>
86 #include <patattr.hxx>
87 #include <stlsheet.hxx>
88 #include <biffhelper.hxx>
93 using namespace ::com::sun::star::awt
;
94 using namespace ::com::sun::star::container
;
95 using namespace ::com::sun::star::style
;
96 using namespace ::com::sun::star::table
;
97 using namespace ::com::sun::star::text
;
98 using namespace ::com::sun::star::uno
;
103 // OOXML constants ------------------------------------------------------------
105 // OOXML predefined color indexes (also used in BIFF3-BIFF8)
106 const sal_Int32 OOX_COLOR_USEROFFSET
= 0; /// First user defined color in palette (OOXML/BIFF12).
108 // OOXML font family (also used in BIFF)
109 const sal_Int32 OOX_FONTFAMILY_NONE
= 0;
110 const sal_Int32 OOX_FONTFAMILY_ROMAN
= 1;
111 const sal_Int32 OOX_FONTFAMILY_SWISS
= 2;
112 const sal_Int32 OOX_FONTFAMILY_MODERN
= 3;
113 const sal_Int32 OOX_FONTFAMILY_SCRIPT
= 4;
114 const sal_Int32 OOX_FONTFAMILY_DECORATIVE
= 5;
116 // OOXML cell text direction (also used in BIFF)
117 const sal_Int32 OOX_XF_TEXTDIR_CONTEXT
= 0;
118 const sal_Int32 OOX_XF_TEXTDIR_LTR
= 1;
119 const sal_Int32 OOX_XF_TEXTDIR_RTL
= 2;
121 // OOXML cell rotation (also used in BIFF)
122 const sal_Int32 OOX_XF_ROTATION_NONE
= 0;
123 const sal_Int32 OOX_XF_ROTATION_STACKED
= 255;
125 // OOXML cell indentation
126 const sal_Int32 OOX_XF_INDENT_NONE
= 0;
128 // OOXML built-in cell styles (also used in BIFF)
129 const sal_Int32 OOX_STYLE_NORMAL
= 0; /// Default cell style.
130 const sal_Int32 OOX_STYLE_ROWLEVEL
= 1; /// RowLevel_x cell style.
131 const sal_Int32 OOX_STYLE_COLLEVEL
= 2; /// ColLevel_x cell style.
133 // BIFF12 constants -----------------------------------------------------------
135 // BIFF12 color types
136 const sal_uInt8 BIFF12_COLOR_AUTO
= 0;
137 const sal_uInt8 BIFF12_COLOR_INDEXED
= 1;
138 const sal_uInt8 BIFF12_COLOR_RGB
= 2;
139 const sal_uInt8 BIFF12_COLOR_THEME
= 3;
141 // BIFF12 diagonal borders
142 const sal_uInt8 BIFF12_BORDER_DIAG_TLBR
= 0x01; /// Top-left to bottom-right.
143 const sal_uInt8 BIFF12_BORDER_DIAG_BLTR
= 0x02; /// Bottom-left to top-right.
145 // BIFF12 gradient fill
146 const sal_Int32 BIFF12_FILL_GRADIENT
= 40;
149 const sal_uInt32 BIFF12_XF_WRAPTEXT
= 0x00400000;
150 const sal_uInt32 BIFF12_XF_JUSTLASTLINE
= 0x00800000;
151 const sal_uInt32 BIFF12_XF_SHRINK
= 0x01000000;
152 const sal_uInt32 BIFF12_XF_LOCKED
= 0x10000000;
153 const sal_uInt32 BIFF12_XF_HIDDEN
= 0x20000000;
155 // BIFF12 XF attribute used flags
156 const sal_uInt16 BIFF12_XF_NUMFMT_USED
= 0x0001;
157 const sal_uInt16 BIFF12_XF_FONT_USED
= 0x0002;
158 const sal_uInt16 BIFF12_XF_ALIGN_USED
= 0x0004;
159 const sal_uInt16 BIFF12_XF_BORDER_USED
= 0x0008;
160 const sal_uInt16 BIFF12_XF_AREA_USED
= 0x0010;
161 const sal_uInt16 BIFF12_XF_PROT_USED
= 0x0020;
163 // BIFF12 DXF constants
164 const sal_uInt16 BIFF12_DXF_FILL_PATTERN
= 0;
165 const sal_uInt16 BIFF12_DXF_FILL_FGCOLOR
= 1;
166 const sal_uInt16 BIFF12_DXF_FILL_BGCOLOR
= 2;
167 const sal_uInt16 BIFF12_DXF_FILL_GRADIENT
= 3;
168 const sal_uInt16 BIFF12_DXF_FILL_STOP
= 4;
169 const sal_uInt16 BIFF12_DXF_FONT_COLOR
= 5;
170 const sal_uInt16 BIFF12_DXF_BORDER_TOP
= 6;
171 const sal_uInt16 BIFF12_DXF_BORDER_BOTTOM
= 7;
172 const sal_uInt16 BIFF12_DXF_BORDER_LEFT
= 8;
173 const sal_uInt16 BIFF12_DXF_BORDER_RIGHT
= 9;
174 const sal_uInt16 BIFF12_DXF_FONT_NAME
= 24;
175 const sal_uInt16 BIFF12_DXF_FONT_WEIGHT
= 25;
176 const sal_uInt16 BIFF12_DXF_FONT_UNDERLINE
= 26;
177 const sal_uInt16 BIFF12_DXF_FONT_ESCAPEMENT
= 27;
178 const sal_uInt16 BIFF12_DXF_FONT_ITALIC
= 28;
179 const sal_uInt16 BIFF12_DXF_FONT_STRIKE
= 29;
180 const sal_uInt16 BIFF12_DXF_FONT_OUTLINE
= 30;
181 const sal_uInt16 BIFF12_DXF_FONT_SHADOW
= 31;
182 const sal_uInt16 BIFF12_DXF_FONT_HEIGHT
= 36;
183 const sal_uInt16 BIFF12_DXF_FONT_SCHEME
= 37;
184 const sal_uInt16 BIFF12_DXF_NUMFMT_CODE
= 38;
185 const sal_uInt16 BIFF12_DXF_NUMFMT_ID
= 41;
186 const sal_uInt16 BIFF12_DXF_CELL_LOCKED
= 43;
187 const sal_uInt16 BIFF12_DXF_CELL_HIDDEN
= 44;
189 // BIFF12 CELLSTYLE flags
190 const sal_uInt16 BIFF12_CELLSTYLE_BUILTIN
= 0x0001;
191 const sal_uInt16 BIFF12_CELLSTYLE_HIDDEN
= 0x0002;
192 const sal_uInt16 BIFF12_CELLSTYLE_CUSTOM
= 0x0004;
194 // BIFF constants -------------------------------------------------------------
196 // BIFF font flags, also used in BIFF12
197 const sal_uInt16 BIFF_FONTFLAG_ITALIC
= 0x0002;
198 const sal_uInt16 BIFF_FONTFLAG_STRIKEOUT
= 0x0008;
199 const sal_uInt16 BIFF_FONTFLAG_OUTLINE
= 0x0010;
200 const sal_uInt16 BIFF_FONTFLAG_SHADOW
= 0x0020;
203 const sal_uInt16 BIFF_FONTWEIGHT_BOLD
= 450;
205 // BIFF font underline, also used in BIFF12
206 const sal_uInt8 BIFF_FONTUNDERL_NONE
= 0;
207 const sal_uInt8 BIFF_FONTUNDERL_SINGLE
= 1;
208 const sal_uInt8 BIFF_FONTUNDERL_DOUBLE
= 2;
209 const sal_uInt8 BIFF_FONTUNDERL_SINGLE_ACC
= 33;
210 const sal_uInt8 BIFF_FONTUNDERL_DOUBLE_ACC
= 34;
212 ::Color
lclReadRgbColor( BinaryInputStream
& rStrm
)
214 sal_uInt8 nR
, nG
, nB
, nA
;
215 nR
= rStrm
.readuChar();
216 nG
= rStrm
.readuChar();
217 nB
= rStrm
.readuChar();
218 nA
= rStrm
.readuChar();
219 sal_Int32 nValue
= nA
;
226 return ::Color(ColorTransparency
, nValue
);
231 ExcelGraphicHelper::ExcelGraphicHelper( const WorkbookHelper
& rHelper
) :
232 GraphicHelper( rHelper
.getBaseFilter().getComponentContext(), rHelper
.getBaseFilter().getTargetFrame(), rHelper
.getBaseFilter().getStorage() ),
233 WorkbookHelper( rHelper
)
237 ::Color
ExcelGraphicHelper::getSchemeColor( sal_Int32 nToken
) const
239 return getTheme().getColorByToken( nToken
);
242 ::Color
ExcelGraphicHelper::getPaletteColor( sal_Int32 nPaletteIdx
) const
244 return getStyles().getPaletteColor( nPaletteIdx
);
247 void XlsColor::setAuto()
249 clearTransformations();
250 setSchemeClr( XML_phClr
);
253 void XlsColor::setRgb( ::Color nRgbValue
, double fTint
)
255 clearTransformations();
256 setSrgbClr( sal_uInt32(nRgbValue
) & 0xFFFFFF );
258 addExcelTintTransformation(fTint
);
261 void XlsColor::setTheme( sal_Int32 nThemeIdx
, double fTint
)
263 clearTransformations();
264 static const sal_Int32 spnColorTokens
[] = {
265 XML_lt1
, XML_dk1
, XML_lt2
, XML_dk2
, XML_accent1
, XML_accent2
,
266 XML_accent3
, XML_accent4
, XML_accent5
, XML_accent6
, XML_hlink
, XML_folHlink
};
267 setSchemeClr( STATIC_ARRAY_SELECT( spnColorTokens
, nThemeIdx
, XML_TOKEN_INVALID
) );
269 addExcelTintTransformation( fTint
);
272 void XlsColor::setIndexed( sal_Int32 nPaletteIdx
, double fTint
)
274 clearTransformations();
275 setPaletteClr( nPaletteIdx
);
277 addExcelTintTransformation(fTint
);
280 void XlsColor::importColor( const AttributeList
& rAttribs
)
282 // tdf#113271 The order of import color is very important in case of more than one color attributes was provided.
283 // This order (theme -> rgb -> indexed -> auto) is not documented and was gathered experimentally based on MS Excel 2013.
284 if (rAttribs
.hasAttribute(XML_theme
))
286 sal_Int32 nTheme
= rAttribs
.getInteger(XML_theme
, -1);
287 double fTint
= rAttribs
.getDouble(XML_tint
, 0.0);
288 setTheme(nTheme
, fTint
);
290 else if( rAttribs
.hasAttribute( XML_rgb
) )
291 setRgb( ::Color(ColorTransparency
, rAttribs
.getIntegerHex( XML_rgb
, sal_Int32(API_RGB_TRANSPARENT
) ) ), rAttribs
.getDouble( XML_tint
, 0.0 ) );
292 else if( rAttribs
.hasAttribute( XML_indexed
) )
293 setIndexed( rAttribs
.getInteger( XML_indexed
, -1 ), rAttribs
.getDouble( XML_tint
, 0.0 ) );
294 else if( rAttribs
.getBool( XML_auto
, false ) )
298 OSL_FAIL( "Color::importColor - unknown color type" );
303 void XlsColor::importColor( SequenceInputStream
& rStrm
)
305 sal_uInt8 nFlags
, nIndex
;
307 nFlags
= rStrm
.readuChar();
308 nIndex
= rStrm
.readuChar();
309 nTint
= rStrm
.readInt16();
311 // scale tint from signed 16-bit to double range -1.0 ... 1.0
312 double fTint
= nTint
;
314 fTint
/= -SAL_MIN_INT16
;
316 fTint
/= SAL_MAX_INT16
;
318 switch( extractValue
< sal_uInt8
>( nFlags
, 1, 7 ) )
320 case BIFF12_COLOR_AUTO
:
324 case BIFF12_COLOR_INDEXED
:
325 setIndexed( nIndex
, fTint
);
328 case BIFF12_COLOR_RGB
:
329 setRgb( lclReadRgbColor( rStrm
), fTint
);
331 case BIFF12_COLOR_THEME
:
332 setTheme( nIndex
, fTint
);
336 OSL_FAIL( "Color::importColor - unknown color type" );
342 void XlsColor::importColorId( SequenceInputStream
& rStrm
)
344 setIndexed( rStrm
.readInt32() );
347 SequenceInputStream
& operator>>( SequenceInputStream
& rStrm
, XlsColor
& orColor
)
349 orColor
.importColor( rStrm
);
355 /** Standard EGA colors, bright. */
356 #define PALETTE_EGA_COLORS_LIGHT \
357 ::Color(0x000000), ::Color(0xFFFFFF), ::Color(0xFF0000), ::Color(0x00FF00), ::Color(0x0000FF), ::Color(0xFFFF00), ::Color(0xFF00FF), ::Color(0x00FFFF)
358 /** Standard EGA colors), dark. */
359 #define PALETTE_EGA_COLORS_DARK \
360 ::Color(0x800000), ::Color(0x008000), ::Color(0x000080), ::Color(0x808000), ::Color(0x800080), ::Color(0x008080), ::Color(0xC0C0C0), ::Color(0x808080)
362 /** Default color table for BIFF8/BIFF12/OOXML. */
363 const ::Color spnDefColors8
[] =
365 /* 0 */ PALETTE_EGA_COLORS_LIGHT
,
366 /* 8 */ PALETTE_EGA_COLORS_LIGHT
,
367 /* 16 */ PALETTE_EGA_COLORS_DARK
,
368 /* 24 */ ::Color(0x9999FF), ::Color(0x993366), ::Color(0xFFFFCC), ::Color(0xCCFFFF), ::Color(0x660066), ::Color(0xFF8080), ::Color(0x0066CC), ::Color(0xCCCCFF),
369 /* 32 */ ::Color(0x000080), ::Color(0xFF00FF), ::Color(0xFFFF00), ::Color(0x00FFFF), ::Color(0x800080), ::Color(0x800000), ::Color(0x008080), ::Color(0x0000FF),
370 /* 40 */ ::Color(0x00CCFF), ::Color(0xCCFFFF), ::Color(0xCCFFCC), ::Color(0xFFFF99), ::Color(0x99CCFF), ::Color(0xFF99CC), ::Color(0xCC99FF), ::Color(0xFFCC99),
371 /* 48 */ ::Color(0x3366FF), ::Color(0x33CCCC), ::Color(0x99CC00), ::Color(0xFFCC00), ::Color(0xFF9900), ::Color(0xFF6600), ::Color(0x666699), ::Color(0x969696),
372 /* 56 */ ::Color(0x003366), ::Color(0x339966), ::Color(0x003300), ::Color(0x333300), ::Color(0x993300), ::Color(0x993366), ::Color(0x333399), ::Color(0x333333)
375 #undef PALETTE_EGA_COLORS_LIGHT
376 #undef PALETTE_EGA_COLORS_DARK
380 ColorPalette::ColorPalette( const WorkbookHelper
& rHelper
)
381 : WorkbookHelper(rHelper
)
385 maColors
.insert( maColors
.begin(), spnDefColors8
, spnDefColors8
+ SAL_N_ELEMENTS(spnDefColors8
) );
386 mnAppendIndex
= OOX_COLOR_USEROFFSET
;
389 void ColorPalette::importPaletteColor( const AttributeList
& rAttribs
)
391 appendColor( ::Color(ColorTransparency
, rAttribs
.getIntegerHex( XML_rgb
, sal_Int32(API_RGB_WHITE
) ) ) );
394 void ColorPalette::importPaletteColor( SequenceInputStream
& rStrm
)
396 ::Color nRgb
= lclReadRgbColor( rStrm
);
400 ::Color
ColorPalette::getColor( sal_Int32 nPaletteIdx
) const
402 ::Color nColor
= API_RGB_TRANSPARENT
;
403 if( const ::Color
* pnPaletteColor
= ContainerHelper::getVectorElement( maColors
, nPaletteIdx
) )
405 nColor
= *pnPaletteColor
;
407 else switch( nPaletteIdx
)
409 case OOX_COLOR_WINDOWTEXT3
:
410 case OOX_COLOR_WINDOWTEXT
:
411 case OOX_COLOR_CHWINDOWTEXT
: nColor
= getBaseFilter().getGraphicHelper().getSystemColor( XML_windowText
); break;
412 case OOX_COLOR_WINDOWBACK3
:
413 case OOX_COLOR_WINDOWBACK
:
414 case OOX_COLOR_CHWINDOWBACK
: nColor
= getBaseFilter().getGraphicHelper().getSystemColor( XML_window
); break;
415 case OOX_COLOR_BUTTONBACK
: nColor
= getBaseFilter().getGraphicHelper().getSystemColor( XML_btnFace
); break;
416 case OOX_COLOR_CHBORDERAUTO
: nColor
= API_RGB_BLACK
; /* really always black? */ break;
417 case OOX_COLOR_NOTEBACK
: nColor
= getBaseFilter().getGraphicHelper().getSystemColor( XML_infoBk
); break;
418 case OOX_COLOR_NOTETEXT
: nColor
= getBaseFilter().getGraphicHelper().getSystemColor( XML_infoText
); break;
419 case OOX_COLOR_FONTAUTO
: nColor
= API_RGB_TRANSPARENT
; break;
420 default: OSL_FAIL( "ColorPalette::getColor - unknown color index" );
425 void ColorPalette::appendColor( ::Color nRGBValue
)
427 if( mnAppendIndex
< maColors
.size() )
428 maColors
[ mnAppendIndex
] = nRGBValue
;
430 maColors
.push_back( nRGBValue
);
436 void lclSetFontName( ApiScriptFontName
& rFontName
, const FontDescriptor
& rFontDesc
, bool bHasGlyphs
)
440 rFontName
.maName
= rFontDesc
.Name
;
441 rFontName
.mnFamily
= rFontDesc
.Family
;
442 // API font descriptor contains rtl_TextEncoding constants
443 rFontName
.mnTextEnc
= rFontDesc
.CharSet
;
447 rFontName
= ApiScriptFontName();
453 FontModel::FontModel() :
454 mnScheme( XML_none
),
455 mnFamily( OOX_FONTFAMILY_NONE
),
456 mnCharSet( WINDOWS_CHARSET_DEFAULT
),
458 mnUnderline( XML_none
),
459 mnEscapement( XML_baseline
),
462 mbStrikeout( false ),
468 void FontModel::setBiff12Scheme( sal_uInt8 nScheme
)
470 static const sal_Int32 spnSchemes
[] = { XML_none
, XML_major
, XML_minor
};
471 mnScheme
= STATIC_ARRAY_SELECT( spnSchemes
, nScheme
, XML_none
);
474 void FontModel::setBiffHeight( sal_uInt16 nHeight
)
476 mfHeight
= nHeight
/ 20.0; // convert twips to points
479 void FontModel::setBiffWeight( sal_uInt16 nWeight
)
481 mbBold
= nWeight
>= BIFF_FONTWEIGHT_BOLD
;
484 void FontModel::setBiffUnderline( sal_uInt16 nUnderline
)
488 case BIFF_FONTUNDERL_NONE
: mnUnderline
= XML_none
; break;
489 case BIFF_FONTUNDERL_SINGLE
: mnUnderline
= XML_single
; break;
490 case BIFF_FONTUNDERL_DOUBLE
: mnUnderline
= XML_double
; break;
491 case BIFF_FONTUNDERL_SINGLE_ACC
: mnUnderline
= XML_singleAccounting
; break;
492 case BIFF_FONTUNDERL_DOUBLE_ACC
: mnUnderline
= XML_doubleAccounting
; break;
493 default: mnUnderline
= XML_none
;
497 void FontModel::setBiffEscapement( sal_uInt16 nEscapement
)
499 static const sal_Int32 spnEscapes
[] = { XML_baseline
, XML_superscript
, XML_subscript
};
500 mnEscapement
= STATIC_ARRAY_SELECT( spnEscapes
, nEscapement
, XML_baseline
);
503 ApiFontUsedFlags::ApiFontUsedFlags( bool bAllUsed
) :
504 mbNameUsed( bAllUsed
),
505 mbColorUsed( bAllUsed
),
506 mbSchemeUsed( bAllUsed
),
507 mbHeightUsed( bAllUsed
),
508 mbUnderlineUsed( bAllUsed
),
509 mbEscapementUsed( bAllUsed
),
510 mbWeightUsed( bAllUsed
),
511 mbPostureUsed( bAllUsed
),
512 mbStrikeoutUsed( bAllUsed
),
513 mbOutlineUsed( bAllUsed
),
514 mbShadowUsed( bAllUsed
)
518 ApiScriptFontName::ApiScriptFontName() :
519 mnFamily( css::awt::FontFamily::DONTKNOW
),
520 mnTextEnc( RTL_TEXTENCODING_DONTKNOW
)
524 ApiFontData::ApiFontData() :
527 220, // height 11 points
530 css::awt::FontFamily::DONTKNOW
,
531 RTL_TEXTENCODING_DONTKNOW
,
532 css::awt::FontPitch::DONTKNOW
,
534 css::awt::FontWeight::NORMAL
,
535 css::awt::FontSlant_NONE
,
536 css::awt::FontUnderline::NONE
,
537 css::awt::FontStrikeout::NONE
,
541 css::awt::FontType::DONTKNOW
),
542 mnColor( API_RGB_TRANSPARENT
),
543 mnEscapement( API_ESCAPE_NONE
),
544 mnEscapeHeight( API_ESCAPEHEIGHT_NONE
),
548 maLatinFont
.maName
= maDesc
.Name
;
551 Font::Font( const WorkbookHelper
& rHelper
, bool bDxf
) :
552 WorkbookHelper( rHelper
),
553 maModel( rHelper
.getTheme().getDefaultFontModel() ),
554 maUsedFlags( !bDxf
),
559 Font::Font( const WorkbookHelper
& rHelper
, FontModel aModel
) :
560 WorkbookHelper( rHelper
),
561 maModel(std::move( aModel
)),
567 void Font::importAttribs( sal_Int32 nElement
, const AttributeList
& rAttribs
)
569 const FontModel
& rDefModel
= getTheme().getDefaultFontModel();
572 case XLS_TOKEN( name
): // when in <font> element
573 case XLS_TOKEN( rFont
): // when in <rPr> element
574 if( rAttribs
.hasAttribute( XML_val
) )
576 maModel
.maName
= rAttribs
.getXString( XML_val
, OUString() );
577 maUsedFlags
.mbNameUsed
= true;
580 case XLS_TOKEN( scheme
):
581 maModel
.mnScheme
= rAttribs
.getToken( XML_val
, rDefModel
.mnScheme
);
583 case XLS_TOKEN( family
):
584 maModel
.mnFamily
= rAttribs
.getInteger( XML_val
, rDefModel
.mnFamily
);
586 case XLS_TOKEN( charset
):
587 maModel
.mnCharSet
= rAttribs
.getInteger( XML_val
, rDefModel
.mnCharSet
);
589 case XLS_TOKEN( sz
):
590 maModel
.mfHeight
= rAttribs
.getDouble( XML_val
, rDefModel
.mfHeight
);
591 maUsedFlags
.mbHeightUsed
= true;
593 case XLS_TOKEN( color
):
594 maModel
.maColor
.importColor( rAttribs
);
595 maUsedFlags
.mbColorUsed
= true;
598 maModel
.mnUnderline
= rAttribs
.getToken( XML_val
, XML_single
);
599 maUsedFlags
.mbUnderlineUsed
= true;
601 case XLS_TOKEN( vertAlign
):
602 maModel
.mnEscapement
= rAttribs
.getToken( XML_val
, XML_baseline
);
603 maUsedFlags
.mbEscapementUsed
= true;
606 maModel
.mbBold
= rAttribs
.getBool( XML_val
, true );
607 maUsedFlags
.mbWeightUsed
= true;
610 maModel
.mbItalic
= rAttribs
.getBool( XML_val
, true );
611 maUsedFlags
.mbPostureUsed
= true;
613 case XLS_TOKEN( strike
):
614 maModel
.mbStrikeout
= rAttribs
.getBool( XML_val
, true );
615 maUsedFlags
.mbStrikeoutUsed
= true;
617 case XLS_TOKEN( outline
):
618 maModel
.mbOutline
= rAttribs
.getBool( XML_val
, true );
619 maUsedFlags
.mbOutlineUsed
= true;
621 case XLS_TOKEN( shadow
):
622 maModel
.mbShadow
= rAttribs
.getBool( XML_val
, true );
623 maUsedFlags
.mbShadowUsed
= true;
628 void Font::importFont( SequenceInputStream
& rStrm
)
630 SAL_WARN_IF( mbDxf
, "sc", "Font::importFont - unexpected conditional formatting flag" );
632 sal_uInt16 nHeight
, nFlags
, nWeight
, nEscapement
;
633 sal_uInt8 nUnderline
, nFamily
, nCharSet
, nScheme
;
634 nHeight
= rStrm
.readuInt16();
635 nFlags
= rStrm
.readuInt16();
636 nWeight
= rStrm
.readuInt16();
637 nEscapement
= rStrm
.readuInt16();
638 nUnderline
= rStrm
.readuChar();
639 nFamily
= rStrm
.readuChar();
640 nCharSet
= rStrm
.readuChar();
642 rStrm
>> maModel
.maColor
;
643 nScheme
= rStrm
.readuChar();
644 rStrm
>> maModel
.maName
;
646 // equal constants in all BIFFs for weight, underline, and escapement
647 maModel
.setBiff12Scheme( nScheme
);
648 maModel
.setBiffHeight( nHeight
);
649 maModel
.setBiffWeight( nWeight
);
650 maModel
.setBiffUnderline( nUnderline
);
651 maModel
.setBiffEscapement( nEscapement
);
652 maModel
.mnFamily
= nFamily
;
653 maModel
.mnCharSet
= nCharSet
;
654 // equal flags in all BIFFs
655 maModel
.mbItalic
= getFlag( nFlags
, BIFF_FONTFLAG_ITALIC
);
656 maModel
.mbStrikeout
= getFlag( nFlags
, BIFF_FONTFLAG_STRIKEOUT
);
657 maModel
.mbOutline
= getFlag( nFlags
, BIFF_FONTFLAG_OUTLINE
);
658 maModel
.mbShadow
= getFlag( nFlags
, BIFF_FONTFLAG_SHADOW
);
661 void Font::importDxfName( SequenceInputStream
& rStrm
)
663 SAL_WARN_IF( !mbDxf
, "sc", "Font::importDxfName - missing conditional formatting flag" );
664 maModel
.maName
= BiffHelper::readString( rStrm
, false );
665 maUsedFlags
.mbColorUsed
= true;
668 void Font::importDxfColor( SequenceInputStream
& rStrm
)
670 SAL_WARN_IF( !mbDxf
, "sc", "Font::importDxfColor - missing conditional formatting flag" );
671 rStrm
>> maModel
.maColor
;
672 maUsedFlags
.mbColorUsed
= true;
675 void Font::importDxfScheme( SequenceInputStream
& rStrm
)
677 SAL_WARN_IF( !mbDxf
, "sc", "Font::importDxfScheme - missing conditional formatting flag" );
678 maModel
.setBiff12Scheme( rStrm
.readuInt8() );
679 maUsedFlags
.mbSchemeUsed
= true;
682 void Font::importDxfHeight( SequenceInputStream
& rStrm
)
684 SAL_WARN_IF( !mbDxf
, "sc", "Font::importDxfHeight - missing conditional formatting flag" );
685 maModel
.setBiffHeight( rStrm
.readuInt16() );
686 maUsedFlags
.mbHeightUsed
= true;
689 void Font::importDxfWeight( SequenceInputStream
& rStrm
)
691 SAL_WARN_IF( !mbDxf
, "sc", "Font::importDxfWeight - missing conditional formatting flag" );
692 maModel
.setBiffWeight( rStrm
.readuInt16() );
693 maUsedFlags
.mbWeightUsed
= true;
696 void Font::importDxfUnderline( SequenceInputStream
& rStrm
)
698 SAL_WARN_IF( !mbDxf
, "sc", "Font::importDxfUnderline - missing conditional formatting flag" );
699 maModel
.setBiffUnderline( rStrm
.readuInt16() );
700 maUsedFlags
.mbUnderlineUsed
= true;
703 void Font::importDxfEscapement( SequenceInputStream
& rStrm
)
705 SAL_WARN_IF( !mbDxf
, "sc", "Font::importDxfEscapement - missing conditional formatting flag" );
706 maModel
.setBiffEscapement( rStrm
.readuInt16() );
707 maUsedFlags
.mbEscapementUsed
= true;
710 void Font::importDxfFlag( sal_Int32 nElement
, SequenceInputStream
& rStrm
)
712 SAL_WARN_IF( !mbDxf
, "sc", "Font::importDxfFlag - missing conditional formatting flag" );
713 bool bFlag
= rStrm
.readuInt8() != 0;
717 maModel
.mbItalic
= bFlag
;
718 maUsedFlags
.mbPostureUsed
= true;
721 maModel
.mbStrikeout
= bFlag
;
722 maUsedFlags
.mbStrikeoutUsed
= true;
725 maModel
.mbOutline
= bFlag
;
726 maUsedFlags
.mbOutlineUsed
= true;
729 maModel
.mbShadow
= bFlag
;
730 maUsedFlags
.mbShadowUsed
= true;
733 OSL_FAIL( "Font::importDxfFlag - unexpected element identifier" );
737 void Font::finalizeImport()
740 maApiData
.maDesc
.Name
= maModel
.maName
;
743 switch( maModel
.mnFamily
)
745 case OOX_FONTFAMILY_NONE
: maApiData
.maDesc
.Family
= css::awt::FontFamily::DONTKNOW
; break;
746 case OOX_FONTFAMILY_ROMAN
: maApiData
.maDesc
.Family
= css::awt::FontFamily::ROMAN
; break;
747 case OOX_FONTFAMILY_SWISS
: maApiData
.maDesc
.Family
= css::awt::FontFamily::SWISS
; break;
748 case OOX_FONTFAMILY_MODERN
: maApiData
.maDesc
.Family
= css::awt::FontFamily::MODERN
; break;
749 case OOX_FONTFAMILY_SCRIPT
: maApiData
.maDesc
.Family
= css::awt::FontFamily::SCRIPT
; break;
750 case OOX_FONTFAMILY_DECORATIVE
: maApiData
.maDesc
.Family
= css::awt::FontFamily::DECORATIVE
; break;
753 // character set (API font descriptor uses rtl_TextEncoding in member CharSet!)
754 if( (0 <= maModel
.mnCharSet
) && (maModel
.mnCharSet
<= SAL_MAX_UINT8
) )
755 maApiData
.maDesc
.CharSet
= static_cast< sal_Int16
>(
756 rtl_getTextEncodingFromWindowsCharset( static_cast< sal_uInt8
>( maModel
.mnCharSet
) ) );
758 // color, height, weight, slant, strikeout, outline, shadow
759 maApiData
.maComplexColor
= maModel
.maColor
.createComplexColor(getBaseFilter().getGraphicHelper(), -1);
760 maApiData
.mnColor
= maModel
.maColor
.getColor( getBaseFilter().getGraphicHelper() );
761 maApiData
.maDesc
.Height
= static_cast< sal_Int16
>( maModel
.mfHeight
* 20.0 );
762 maApiData
.maDesc
.Weight
= maModel
.mbBold
? css::awt::FontWeight::BOLD
: css::awt::FontWeight::NORMAL
;
763 maApiData
.maDesc
.Slant
= maModel
.mbItalic
? css::awt::FontSlant_ITALIC
: css::awt::FontSlant_NONE
;
764 maApiData
.maDesc
.Strikeout
= maModel
.mbStrikeout
? css::awt::FontStrikeout::SINGLE
: css::awt::FontStrikeout::NONE
;
765 maApiData
.mbOutline
= maModel
.mbOutline
;
766 maApiData
.mbShadow
= maModel
.mbShadow
;
769 switch( maModel
.mnUnderline
)
771 case XML_double
: maApiData
.maDesc
.Underline
= css::awt::FontUnderline::DOUBLE
; break;
772 case XML_doubleAccounting
: maApiData
.maDesc
.Underline
= css::awt::FontUnderline::DOUBLE
; break;
773 case XML_none
: maApiData
.maDesc
.Underline
= css::awt::FontUnderline::NONE
; break;
774 case XML_single
: maApiData
.maDesc
.Underline
= css::awt::FontUnderline::SINGLE
; break;
775 case XML_singleAccounting
: maApiData
.maDesc
.Underline
= css::awt::FontUnderline::SINGLE
; break;
779 switch( maModel
.mnEscapement
)
782 maApiData
.mnEscapement
= API_ESCAPE_NONE
;
783 maApiData
.mnEscapeHeight
= API_ESCAPEHEIGHT_NONE
;
785 case XML_superscript
:
786 maApiData
.mnEscapement
= API_ESCAPE_SUPERSCRIPT
;
787 maApiData
.mnEscapeHeight
= API_ESCAPEHEIGHT_DEFAULT
;
790 maApiData
.mnEscapement
= API_ESCAPE_SUBSCRIPT
;
791 maApiData
.mnEscapeHeight
= API_ESCAPEHEIGHT_DEFAULT
;
795 // supported script types
796 if( !maUsedFlags
.mbNameUsed
)
799 // For caching if the font has glyphs then the underline and strike-through don't matter.
800 // Those aren't differences in the actual font, so just zero those out for the cache.
801 // The weight and pitch are different faces though, and there are some fonts with glyphs
802 // missing in one or other variant.
803 css::awt::FontDescriptor aGlyphDesc
= maApiData
.maDesc
;
804 aGlyphDesc
.Strikeout
= css::awt::FontStrikeout::NONE
;
805 aGlyphDesc
.Underline
= css::awt::FontUnderline::NONE
;
806 // Never seen that to be the case for font *sizes* however, so we can use a uniform 10pt size
807 aGlyphDesc
.Height
= 200;
809 bool bHasAsian(false), bHasCmplx(false), bHasLatin(false);
810 FontClassificationMap
& rFontClassificationCache
= getFontClassificationCache();
811 if (auto found
= rFontClassificationCache
.find(aGlyphDesc
); found
!= rFontClassificationCache
.end())
813 FontClassification eClassification
= found
->second
;
814 bHasAsian
= bool(eClassification
& FontClassification::Asian
);
815 bHasCmplx
= bool(eClassification
& FontClassification::Cmplx
);
816 bHasLatin
= bool(eClassification
& FontClassification::Latin
);
820 PropertySet
aDocProps(( Reference
< css::beans::XPropertySet
>(getDocument()) ));
821 Reference
< XDevice
> xDevice( aDocProps
.getAnyProperty( PROP_ReferenceDevice
), UNO_QUERY
);
825 Reference
< XFont2
> xFont( xDevice
->getFont(aGlyphDesc
), UNO_QUERY
);
831 xFont
->hasGlyphs( OUString( u
'\x3041' ) ) || // 3040-309F: Hiragana
832 xFont
->hasGlyphs( OUString( u
'\x30A1' ) ) || // 30A0-30FF: Katakana
833 xFont
->hasGlyphs( OUString( u
'\x3111' ) ) || // 3100-312F: Bopomofo
834 xFont
->hasGlyphs( OUString( u
'\x3131' ) ) || // 3130-318F: Hangul Compatibility Jamo
835 xFont
->hasGlyphs( OUString( u
'\x3301' ) ) || // 3300-33FF: CJK Compatibility
836 xFont
->hasGlyphs( OUString( u
'\x3401' ) ) || // 3400-4DBF: CJK Unified Ideographs Extension A
837 xFont
->hasGlyphs( OUString( u
'\x4E01' ) ) || // 4E00-9FFF: CJK Unified Ideographs
838 xFont
->hasGlyphs( OUString( u
'\x7E01' ) ) || // 4E00-9FFF: CJK Unified Ideographs
839 xFont
->hasGlyphs( OUString( u
'\xA001' ) ) || // A001-A48F: Yi Syllables
840 xFont
->hasGlyphs( OUString( u
'\xAC01' ) ) || // AC00-D7AF: Hangul Syllables
841 xFont
->hasGlyphs( OUString( u
'\xCC01' ) ) || // AC00-D7AF: Hangul Syllables
842 xFont
->hasGlyphs( OUString( u
'\xF901' ) ) || // F900-FAFF: CJK Compatibility Ideographs
843 xFont
->hasGlyphs( OUString( u
'\xFF71' ) ); // FF00-FFEF: Halfwidth/Fullwidth Forms
844 // #113783# CTL fonts
846 xFont
->hasGlyphs( OUString( u
'\x05D1' ) ) || // 0590-05FF: Hebrew
847 xFont
->hasGlyphs( OUString( u
'\x0631' ) ) || // 0600-06FF: Arabic
848 xFont
->hasGlyphs( OUString( u
'\x0721' ) ) || // 0700-074F: Syriac
849 xFont
->hasGlyphs( OUString( u
'\x0911' ) ) || // 0900-0DFF: Indic scripts
850 xFont
->hasGlyphs( OUString( u
'\x0E01' ) ) || // 0E00-0E7F: Thai
851 xFont
->hasGlyphs( OUString( u
'\xFB21' ) ) || // FB1D-FB4F: Hebrew Presentation Forms
852 xFont
->hasGlyphs( OUString( u
'\xFB51' ) ) || // FB50-FDFF: Arabic Presentation Forms-A
853 xFont
->hasGlyphs( OUString( u
'\xFE71' ) ); // FE70-FEFF: Arabic Presentation Forms-B
856 (!bHasAsian
&& !bHasCmplx
) ||
857 xFont
->hasGlyphs( OUString( 'A' ) );
859 FontClassification
eClassification(FontClassification::None
);
861 eClassification
= eClassification
| FontClassification::Asian
;
863 eClassification
= eClassification
| FontClassification::Cmplx
;
865 eClassification
= eClassification
| FontClassification::Latin
;
866 rFontClassificationCache
.emplace(aGlyphDesc
, eClassification
);
869 lclSetFontName( maApiData
.maLatinFont
, maApiData
.maDesc
, bHasLatin
);
870 lclSetFontName( maApiData
.maAsianFont
, maApiData
.maDesc
, bHasAsian
);
871 lclSetFontName( maApiData
.maCmplxFont
, maApiData
.maDesc
, bHasCmplx
);
874 bool Font::needsRichTextFormat() const
876 return maApiData
.mnEscapement
!= API_ESCAPE_NONE
;
879 static ::FontFamily
lcl_getFontFamily( sal_Int32 nFamily
)
881 ::FontFamily eScFamily
= FAMILY_DONTKNOW
;
884 case css::awt::FontFamily::DONTKNOW
:
885 eScFamily
= FAMILY_DONTKNOW
;
887 case css::awt::FontFamily::ROMAN
:
888 eScFamily
= FAMILY_ROMAN
;
890 case css::awt::FontFamily::SWISS
:
891 eScFamily
= FAMILY_SWISS
;
893 case css::awt::FontFamily::MODERN
:
894 eScFamily
= FAMILY_MODERN
;
896 case css::awt::FontFamily::SCRIPT
:
897 eScFamily
= FAMILY_SCRIPT
;
899 case css::awt::FontFamily::DECORATIVE
:
900 eScFamily
= FAMILY_DECORATIVE
;
906 void Font::fillToItemSet( SfxItemSet
& rItemSet
, bool bEditEngineText
, bool bSkipPoolDefs
) const
908 if ( maUsedFlags
.mbNameUsed
)
910 if( !maApiData
.maLatinFont
.maName
.isEmpty() )
912 rtl_TextEncoding eFontEnc
= maApiData
.maLatinFont
.mnTextEnc
;
913 // taken from binary importer
914 rtl_TextEncoding eTempTextEnc
= (bEditEngineText
&& (eFontEnc
== getTextEncoding())) ?
915 ScfTools::GetSystemTextEncoding() : eFontEnc
;
917 SvxFontItem
aFontItem( lcl_getFontFamily( maApiData
.maLatinFont
.mnFamily
), maApiData
.maLatinFont
.maName
, OUString(),
918 PITCH_DONTKNOW
, eTempTextEnc
, ATTR_FONT
);
919 ScfTools::PutItem( rItemSet
, aFontItem
, bEditEngineText
? static_cast<sal_uInt16
>(EE_CHAR_FONTINFO
) : ATTR_FONT
, bSkipPoolDefs
);
921 if( !maApiData
.maAsianFont
.maName
.isEmpty() )
923 rtl_TextEncoding eFontEnc
= maApiData
.maAsianFont
.mnTextEnc
;
924 // taken from binary importer
925 rtl_TextEncoding eTempTextEnc
= (bEditEngineText
&& (eFontEnc
== getTextEncoding())) ?
926 ScfTools::GetSystemTextEncoding() : eFontEnc
;
927 SvxFontItem
aFontItem( lcl_getFontFamily( maApiData
.maAsianFont
.mnFamily
), maApiData
.maAsianFont
.maName
, OUString(),
928 PITCH_DONTKNOW
, eTempTextEnc
, ATTR_FONT
);
929 ScfTools::PutItem( rItemSet
, aFontItem
, bEditEngineText
? static_cast<sal_uInt16
>(EE_CHAR_FONTINFO_CJK
) : ATTR_CJK_FONT
, bSkipPoolDefs
);
931 if( !maApiData
.maCmplxFont
.maName
.isEmpty() )
933 rtl_TextEncoding eFontEnc
= maApiData
.maCmplxFont
.mnTextEnc
;
934 // taken from binary importer
935 rtl_TextEncoding eTempTextEnc
= (bEditEngineText
&& (eFontEnc
== getTextEncoding())) ?
936 ScfTools::GetSystemTextEncoding() : eFontEnc
;
937 SvxFontItem
aFontItem( lcl_getFontFamily( maApiData
.maCmplxFont
.mnFamily
), maApiData
.maCmplxFont
.maName
, OUString(),
938 PITCH_DONTKNOW
, eTempTextEnc
, ATTR_FONT
);
939 ScfTools::PutItem( rItemSet
, aFontItem
, bEditEngineText
? static_cast<sal_uInt16
>(EE_CHAR_FONTINFO_CTL
) : ATTR_CTL_FONT
, bSkipPoolDefs
);
943 if( maUsedFlags
.mbHeightUsed
)
945 sal_Int32 nHeight
= maApiData
.maDesc
.Height
;
946 // do we use XclFontItemType::HeaderFooter ( or is it just relevant for the binary filter )
947 if( bEditEngineText
/* && (eType != XclFontItemType::HeaderFooter) */) // do not convert header/footer height
948 nHeight
= convertTwipToMm100(nHeight
);
949 SvxFontHeightItem
aHeightItem( nHeight
, 100, ATTR_FONT_HEIGHT
);
950 ScfTools::PutItem( rItemSet
, aHeightItem
, bEditEngineText
? static_cast<sal_uInt16
>(EE_CHAR_FONTHEIGHT
) : ATTR_FONT_HEIGHT
, bSkipPoolDefs
);
951 ScfTools::PutItem( rItemSet
, aHeightItem
, bEditEngineText
? static_cast<sal_uInt16
>(EE_CHAR_FONTHEIGHT_CJK
) : ATTR_CJK_FONT_HEIGHT
, bSkipPoolDefs
);
952 ScfTools::PutItem( rItemSet
, aHeightItem
, bEditEngineText
? static_cast<sal_uInt16
>(EE_CHAR_FONTHEIGHT_CTL
) : ATTR_CTL_FONT_HEIGHT
, bSkipPoolDefs
);
955 if( maUsedFlags
.mbWeightUsed
)
957 ::FontWeight fWeight
= vcl::unohelper::ConvertFontWeight( maApiData
.maDesc
.Weight
);
958 SvxWeightItem
aWeightItem( fWeight
, ATTR_FONT_WEIGHT
);
959 ScfTools::PutItem( rItemSet
, aWeightItem
, bEditEngineText
? static_cast<sal_uInt16
>(EE_CHAR_WEIGHT
) : ATTR_FONT_WEIGHT
, bSkipPoolDefs
);
960 ScfTools::PutItem( rItemSet
, aWeightItem
, bEditEngineText
? static_cast<sal_uInt16
>(EE_CHAR_WEIGHT_CTL
) : ATTR_CTL_FONT_WEIGHT
, bSkipPoolDefs
);
961 ScfTools::PutItem( rItemSet
, aWeightItem
, bEditEngineText
? static_cast<sal_uInt16
>(EE_CHAR_WEIGHT_CJK
) : ATTR_CJK_FONT_WEIGHT
, bSkipPoolDefs
);
964 if( maUsedFlags
.mbPostureUsed
)
966 SvxPostureItem
aPostItem( ( maApiData
.maDesc
.Slant
== css::awt::FontSlant_ITALIC
) ? ITALIC_NORMAL
: ITALIC_NONE
, ATTR_FONT_POSTURE
);
967 ScfTools::PutItem( rItemSet
, aPostItem
, bEditEngineText
? static_cast<sal_uInt16
>(EE_CHAR_ITALIC
) : ATTR_FONT_POSTURE
, bSkipPoolDefs
);
968 ScfTools::PutItem( rItemSet
, aPostItem
, bEditEngineText
? static_cast<sal_uInt16
>(EE_CHAR_ITALIC_CJK
) : ATTR_CJK_FONT_POSTURE
, bSkipPoolDefs
);
969 ScfTools::PutItem( rItemSet
, aPostItem
, bEditEngineText
? static_cast<sal_uInt16
>(EE_CHAR_ITALIC_CTL
) : ATTR_CTL_FONT_POSTURE
, bSkipPoolDefs
);
972 if( maUsedFlags
.mbColorUsed
)
974 ScfTools::PutItem( rItemSet
,SvxColorItem( maApiData
.mnColor
, maApiData
.maComplexColor
, bEditEngineText
? static_cast<sal_uInt16
>(EE_CHAR_COLOR
) : ATTR_FONT_COLOR
), bSkipPoolDefs
);
977 if( maUsedFlags
.mbUnderlineUsed
)
979 FontLineStyle eScUnderl
;
980 if ( maApiData
.maDesc
.Underline
== css::awt::FontUnderline::DOUBLE
)
981 eScUnderl
= LINESTYLE_DOUBLE
;
982 else if ( maApiData
.maDesc
.Underline
== css::awt::FontUnderline::SINGLE
)
983 eScUnderl
= LINESTYLE_SINGLE
;
985 eScUnderl
= LINESTYLE_NONE
;
986 SvxUnderlineItem
aUnderlItem( eScUnderl
, ATTR_FONT_UNDERLINE
);
987 ScfTools::PutItem( rItemSet
, aUnderlItem
, bEditEngineText
? static_cast<sal_uInt16
>(EE_CHAR_UNDERLINE
) : ATTR_FONT_UNDERLINE
, bSkipPoolDefs
);
990 if( maUsedFlags
.mbStrikeoutUsed
)
992 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
);
996 if( maUsedFlags
.mbOutlineUsed
)
998 ScfTools::PutItem( rItemSet
, SvxContourItem( maApiData
.mbOutline
, ATTR_FONT_CONTOUR
), bEditEngineText
? static_cast<sal_uInt16
>(EE_CHAR_OUTLINE
) : ATTR_FONT_CONTOUR
, bSkipPoolDefs
);
1002 if( maUsedFlags
.mbShadowUsed
)
1004 ScfTools::PutItem( rItemSet
, SvxShadowedItem( maApiData
.mbShadow
, ATTR_FONT_SHADOWED
), bEditEngineText
? static_cast<sal_uInt16
>(EE_CHAR_SHADOW
) : ATTR_FONT_SHADOWED
, bSkipPoolDefs
);
1006 if( !maUsedFlags
.mbEscapementUsed
)
1009 SvxEscapement eScEscapem
= SvxEscapement::Off
;
1010 if ( maApiData
.mnEscapement
== API_ESCAPE_SUPERSCRIPT
)
1011 eScEscapem
= SvxEscapement::Superscript
;
1012 else if ( maApiData
.mnEscapement
== API_ESCAPE_SUBSCRIPT
)
1013 eScEscapem
= SvxEscapement::Subscript
;
1014 if( bEditEngineText
)
1016 // #TODO handle EscapementHeight
1017 rItemSet
.Put( SvxEscapementItem( eScEscapem
, EE_CHAR_ESCAPEMENT
) );
1021 void Font::writeToPropertyMap( PropertyMap
& rPropMap
) const
1023 // font name properties
1024 if( maUsedFlags
.mbNameUsed
)
1026 if( !maApiData
.maLatinFont
.maName
.isEmpty() )
1028 rPropMap
.setProperty( PROP_CharFontName
, maApiData
.maLatinFont
.maName
);
1029 rPropMap
.setProperty( PROP_CharFontFamily
, maApiData
.maLatinFont
.mnFamily
);
1030 rPropMap
.setProperty( PROP_CharFontCharSet
, maApiData
.maLatinFont
.mnTextEnc
);
1032 if( !maApiData
.maAsianFont
.maName
.isEmpty() )
1034 rPropMap
.setProperty( PROP_CharFontNameAsian
, maApiData
.maAsianFont
.maName
);
1035 rPropMap
.setProperty( PROP_CharFontFamilyAsian
, maApiData
.maAsianFont
.mnFamily
);
1036 rPropMap
.setProperty( PROP_CharFontCharSetAsian
, maApiData
.maAsianFont
.mnTextEnc
);
1038 if( !maApiData
.maCmplxFont
.maName
.isEmpty() )
1040 rPropMap
.setProperty( PROP_CharFontNameComplex
, maApiData
.maCmplxFont
.maName
);
1041 rPropMap
.setProperty( PROP_CharFontFamilyComplex
, maApiData
.maCmplxFont
.mnFamily
);
1042 rPropMap
.setProperty( PROP_CharFontCharSetComplex
, maApiData
.maCmplxFont
.mnTextEnc
);
1046 if( maUsedFlags
.mbHeightUsed
)
1048 float fHeight
= static_cast< float >( maApiData
.maDesc
.Height
/ 20.0 ); // twips to points
1049 rPropMap
.setProperty( PROP_CharHeight
, fHeight
);
1050 rPropMap
.setProperty( PROP_CharHeightAsian
, fHeight
);
1051 rPropMap
.setProperty( PROP_CharHeightComplex
, fHeight
);
1054 if( maUsedFlags
.mbWeightUsed
)
1056 float fWeight
= maApiData
.maDesc
.Weight
;
1057 rPropMap
.setProperty( PROP_CharWeight
, fWeight
);
1058 rPropMap
.setProperty( PROP_CharWeightAsian
, fWeight
);
1059 rPropMap
.setProperty( PROP_CharWeightComplex
, fWeight
);
1062 if( maUsedFlags
.mbPostureUsed
)
1064 rPropMap
.setProperty( PROP_CharPosture
, maApiData
.maDesc
.Slant
);
1065 rPropMap
.setProperty( PROP_CharPostureAsian
, maApiData
.maDesc
.Slant
);
1066 rPropMap
.setProperty( PROP_CharPostureComplex
, maApiData
.maDesc
.Slant
);
1069 if( maUsedFlags
.mbColorUsed
)
1070 rPropMap
.setProperty( PROP_CharColor
, maApiData
.mnColor
);
1072 if( maUsedFlags
.mbUnderlineUsed
)
1073 rPropMap
.setProperty( PROP_CharUnderline
, maApiData
.maDesc
.Underline
);
1075 if( maUsedFlags
.mbStrikeoutUsed
)
1076 rPropMap
.setProperty( PROP_CharStrikeout
, maApiData
.maDesc
.Strikeout
);
1078 if( maUsedFlags
.mbOutlineUsed
)
1079 rPropMap
.setProperty( PROP_CharContoured
, maApiData
.mbOutline
);
1081 if( maUsedFlags
.mbShadowUsed
)
1082 rPropMap
.setProperty( PROP_CharShadowed
, maApiData
.mbShadow
);
1084 if( maUsedFlags
.mbEscapementUsed
)
1086 rPropMap
.setProperty( PROP_CharEscapement
, maApiData
.mnEscapement
);
1087 rPropMap
.setProperty( PROP_CharEscapementHeight
, maApiData
.mnEscapeHeight
);
1091 void Font::writeToPropertySet( PropertySet
& rPropSet
) const
1093 PropertyMap aPropMap
;
1094 writeToPropertyMap( aPropMap
);
1095 rPropSet
.setProperties( aPropMap
);
1098 AlignmentModel::AlignmentModel() :
1099 mnHorAlign( XML_general
),
1100 mnVerAlign( XML_bottom
),
1101 mnTextDir( OOX_XF_TEXTDIR_CONTEXT
),
1102 mnRotation( OOX_XF_ROTATION_NONE
),
1103 mnIndent( OOX_XF_INDENT_NONE
),
1104 mbWrapText( false ),
1106 mbJustLastLine( false )
1110 void AlignmentModel::setBiffHorAlign( sal_uInt8 nHorAlign
)
1112 static const sal_Int32 spnHorAligns
[] = {
1113 XML_general
, XML_left
, XML_center
, XML_right
,
1114 XML_fill
, XML_justify
, XML_centerContinuous
, XML_distributed
};
1115 mnHorAlign
= STATIC_ARRAY_SELECT( spnHorAligns
, nHorAlign
, XML_general
);
1118 void AlignmentModel::setBiffVerAlign( sal_uInt8 nVerAlign
)
1120 static const sal_Int32 spnVerAligns
[] = {
1121 XML_top
, XML_center
, XML_bottom
, XML_justify
, XML_distributed
};
1122 mnVerAlign
= STATIC_ARRAY_SELECT( spnVerAligns
, nVerAlign
, XML_bottom
);
1125 ApiAlignmentData::ApiAlignmentData() :
1126 meHorJustify( css::table::CellHoriJustify_STANDARD
),
1127 mnHorJustifyMethod( css::table::CellJustifyMethod::AUTO
),
1128 mnVerJustify( css::table::CellVertJustify2::STANDARD
),
1129 mnVerJustifyMethod( css::table::CellJustifyMethod::AUTO
),
1130 meOrientation( css::table::CellOrientation_STANDARD
),
1132 mnWritingMode( css::text::WritingMode2::PAGE
),
1134 mbWrapText( false ),
1139 bool operator==( const ApiAlignmentData
& rLeft
, const ApiAlignmentData
& rRight
)
1142 (rLeft
.meHorJustify
== rRight
.meHorJustify
) &&
1143 (rLeft
.mnHorJustifyMethod
== rRight
.mnHorJustifyMethod
) &&
1144 (rLeft
.mnVerJustify
== rRight
.mnVerJustify
) &&
1145 (rLeft
.mnVerJustifyMethod
== rRight
.mnVerJustifyMethod
) &&
1146 (rLeft
.meOrientation
== rRight
.meOrientation
) &&
1147 (rLeft
.mnRotation
== rRight
.mnRotation
) &&
1148 (rLeft
.mnWritingMode
== rRight
.mnWritingMode
) &&
1149 (rLeft
.mnIndent
== rRight
.mnIndent
) &&
1150 (rLeft
.mbWrapText
== rRight
.mbWrapText
) &&
1151 (rLeft
.mbShrink
== rRight
.mbShrink
);
1154 Alignment::Alignment( const WorkbookHelper
& rHelper
) :
1155 WorkbookHelper( rHelper
)
1159 void Alignment::importAlignment( const AttributeList
& rAttribs
)
1161 maModel
.mnVerAlign
= rAttribs
.getToken( XML_vertical
, XML_bottom
);
1162 maModel
.mnTextDir
= rAttribs
.getInteger( XML_readingOrder
, OOX_XF_TEXTDIR_CONTEXT
);
1163 maModel
.mnRotation
= rAttribs
.getInteger( XML_textRotation
, OOX_XF_ROTATION_NONE
);
1164 sal_Int32 nDefaultHorAlign
= XML_general
;
1165 if (maModel
.mnRotation
!= OOX_XF_ROTATION_NONE
)
1167 if (maModel
.mnRotation
< 90 || maModel
.mnRotation
== 180)
1169 nDefaultHorAlign
= XML_left
;
1173 nDefaultHorAlign
= XML_right
;
1176 maModel
.mnHorAlign
= rAttribs
.getToken( XML_horizontal
, nDefaultHorAlign
);
1177 maModel
.mnIndent
= rAttribs
.getInteger( XML_indent
, OOX_XF_INDENT_NONE
);
1178 maModel
.mbWrapText
= rAttribs
.getBool( XML_wrapText
, false );
1179 maModel
.mbShrink
= rAttribs
.getBool( XML_shrinkToFit
, false );
1180 maModel
.mbJustLastLine
= rAttribs
.getBool( XML_justifyLastLine
, false );
1183 void Alignment::setBiff12Data( sal_uInt32 nFlags
)
1185 maModel
.setBiffHorAlign( extractValue
< sal_uInt8
>( nFlags
, 16, 3 ) );
1186 maModel
.setBiffVerAlign( extractValue
< sal_uInt8
>( nFlags
, 19, 3 ) );
1187 maModel
.mnTextDir
= extractValue
< sal_Int32
>( nFlags
, 26, 2 );
1188 maModel
.mnRotation
= extractValue
< sal_Int32
>( nFlags
, 0, 8 );
1189 maModel
.mnIndent
= extractValue
< sal_uInt8
>( nFlags
, 8, 8 );
1190 maModel
.mbWrapText
= getFlag( nFlags
, BIFF12_XF_WRAPTEXT
);
1191 maModel
.mbShrink
= getFlag( nFlags
, BIFF12_XF_SHRINK
);
1192 maModel
.mbJustLastLine
= getFlag( nFlags
, BIFF12_XF_JUSTLASTLINE
);
1195 void Alignment::finalizeImport()
1197 // horizontal alignment
1198 switch( maModel
.mnHorAlign
)
1200 case XML_center
: maApiData
.meHorJustify
= css::table::CellHoriJustify_CENTER
; break;
1201 case XML_centerContinuous
: maApiData
.meHorJustify
= css::table::CellHoriJustify_CENTER
; break;
1202 case XML_distributed
: maApiData
.meHorJustify
= css::table::CellHoriJustify_BLOCK
; break;
1203 case XML_fill
: maApiData
.meHorJustify
= css::table::CellHoriJustify_REPEAT
; break;
1204 case XML_general
: maApiData
.meHorJustify
= css::table::CellHoriJustify_STANDARD
; break;
1205 case XML_justify
: maApiData
.meHorJustify
= css::table::CellHoriJustify_BLOCK
; break;
1206 case XML_left
: maApiData
.meHorJustify
= css::table::CellHoriJustify_LEFT
; break;
1207 case XML_right
: maApiData
.meHorJustify
= css::table::CellHoriJustify_RIGHT
; break;
1210 if (maModel
.mnHorAlign
== XML_distributed
)
1211 maApiData
.mnHorJustifyMethod
= css::table::CellJustifyMethod::DISTRIBUTE
;
1213 // vertical alignment
1214 switch( maModel
.mnVerAlign
)
1216 case XML_bottom
: maApiData
.mnVerJustify
= css::table::CellVertJustify2::BOTTOM
; break;
1217 case XML_center
: maApiData
.mnVerJustify
= css::table::CellVertJustify2::CENTER
; break;
1218 case XML_distributed
: maApiData
.mnVerJustify
= css::table::CellVertJustify2::BLOCK
; break;
1219 case XML_justify
: maApiData
.mnVerJustify
= css::table::CellVertJustify2::BLOCK
; break;
1220 case XML_top
: maApiData
.mnVerJustify
= css::table::CellVertJustify2::TOP
; break;
1223 if (maModel
.mnVerAlign
== XML_distributed
)
1224 maApiData
.mnVerJustifyMethod
= css::table::CellJustifyMethod::DISTRIBUTE
;
1226 /* indentation: expressed as number of blocks of 3 space characters in
1228 UnitConverter
& rUnitConverter
= getUnitConverter();
1229 // Note: indents are stored in twips
1230 sal_Int32 nIndent
= rUnitConverter
.scaleValue( 3.0 * maModel
.mnIndent
, Unit::Space
, Unit::Twip
);
1231 if( (0 <= nIndent
) && (nIndent
<= SAL_MAX_INT16
) )
1232 maApiData
.mnIndent
= static_cast< sal_Int16
>( nIndent
);
1234 // complex text direction
1235 switch( maModel
.mnTextDir
)
1237 case OOX_XF_TEXTDIR_CONTEXT
: maApiData
.mnWritingMode
= css::text::WritingMode2::PAGE
; break;
1238 case OOX_XF_TEXTDIR_LTR
: maApiData
.mnWritingMode
= css::text::WritingMode2::LR_TB
; break;
1239 case OOX_XF_TEXTDIR_RTL
: maApiData
.mnWritingMode
= css::text::WritingMode2::RL_TB
; break;
1242 // rotation: 0-90 means 0 to 90 degrees ccw, 91-180 means 1 to 90 degrees cw, 255 means stacked
1243 sal_Int32 nOoxRot
= maModel
.mnRotation
;
1244 maApiData
.mnRotation
= Degree100(((0 <= nOoxRot
) && (nOoxRot
<= 90)) ?
1246 (((91 <= nOoxRot
) && (nOoxRot
<= 180)) ? (100 * (450 - nOoxRot
)) : 0));
1248 // "Orientation" property used for character stacking
1249 maApiData
.meOrientation
= (nOoxRot
== OOX_XF_ROTATION_STACKED
) ?
1250 css::table::CellOrientation_STACKED
: css::table::CellOrientation_STANDARD
;
1252 // alignment flags (#i84960 automatic line break, if vertically justified/distributed)
1253 maApiData
.mbWrapText
= maModel
.mbWrapText
|| (maModel
.mnVerAlign
== XML_distributed
) || (maModel
.mnVerAlign
== XML_justify
);
1254 maApiData
.mbShrink
= maModel
.mbShrink
;
1258 ::SvxCellVerJustify
Alignment::GetScVerAlign() const
1260 ::SvxCellVerJustify nVert
= ::SvxCellVerJustify::Standard
;
1261 switch ( maApiData
.mnVerJustify
)
1263 case css::table::CellVertJustify2::BOTTOM
:
1264 nVert
= ::SvxCellVerJustify::Bottom
;
1266 case css::table::CellVertJustify2::CENTER
:
1267 nVert
= ::SvxCellVerJustify::Center
;
1269 case css::table::CellVertJustify2::TOP
:
1270 nVert
= ::SvxCellVerJustify::Top
;
1272 case css::table::CellVertJustify2::BLOCK
:
1273 nVert
= ::SvxCellVerJustify::Block
;
1275 case css::table::CellVertJustify2::STANDARD
:
1277 nVert
= ::SvxCellVerJustify::Standard
;
1283 ::SvxCellHorJustify
Alignment::GetScHorAlign() const
1285 ::SvxCellHorJustify nHori
= ::SvxCellHorJustify::Standard
;
1286 switch( maApiData
.meHorJustify
)
1288 case css::table::CellHoriJustify_LEFT
:
1289 nHori
= ::SvxCellHorJustify::Left
;
1291 case css::table::CellHoriJustify_CENTER
:
1292 nHori
= ::SvxCellHorJustify::Center
;
1294 case css::table::CellHoriJustify_RIGHT
:
1295 nHori
= ::SvxCellHorJustify::Right
;
1297 case css::table::CellHoriJustify_BLOCK
:
1298 nHori
= ::SvxCellHorJustify::Block
;
1300 case css::table::CellHoriJustify_REPEAT
:
1301 nHori
= ::SvxCellHorJustify::Repeat
;
1303 case css::table::CellHoriJustify_STANDARD
:
1305 nHori
= ::SvxCellHorJustify::Standard
;
1311 SvxFrameDirection
Alignment::GetScFrameDir() const
1313 SvxFrameDirection eFrameDir
= SvxFrameDirection::Environment
;
1314 switch( maApiData
.mnWritingMode
)
1316 case css::text::WritingMode2::PAGE
:
1317 eFrameDir
= SvxFrameDirection::Environment
;
1319 case css::text::WritingMode2::LR_TB
:
1320 eFrameDir
= SvxFrameDirection::Horizontal_LR_TB
;
1322 case css::text::WritingMode2::RL_TB
:
1323 eFrameDir
= SvxFrameDirection::Horizontal_RL_TB
;
1326 OSL_FAIL( "GetScFrameDir - unknown CTL text direction" );
1331 void Alignment::fillToItemSet( SfxItemSet
& rItemSet
, bool bSkipPoolDefs
) const
1333 // horizontal alignment
1334 ScfTools::PutItem( rItemSet
, SvxHorJustifyItem( GetScHorAlign(), ATTR_HOR_JUSTIFY
), bSkipPoolDefs
);
1335 ScfTools::PutItem( rItemSet
, SvxJustifyMethodItem( ( maApiData
.mnHorJustifyMethod
== css::table::CellJustifyMethod::DISTRIBUTE
) ? ::SvxCellJustifyMethod::Distribute
: ::SvxCellJustifyMethod::Auto
, ATTR_HOR_JUSTIFY_METHOD
), bSkipPoolDefs
);
1336 ScfTools::PutItem( rItemSet
, SvxVerJustifyItem( GetScVerAlign(), ATTR_VER_JUSTIFY
), bSkipPoolDefs
);
1337 // vertical alignment
1338 ScfTools::PutItem( rItemSet
, SvxJustifyMethodItem( ( maApiData
.mnVerJustifyMethod
== css::table::CellJustifyMethod::DISTRIBUTE
) ? ::SvxCellJustifyMethod::Distribute
: ::SvxCellJustifyMethod::Auto
, ATTR_VER_JUSTIFY_METHOD
), bSkipPoolDefs
);
1340 // CTL text direction
1341 ScfTools::PutItem( rItemSet
, SvxFrameDirectionItem( GetScFrameDir(), ATTR_WRITINGDIR
), bSkipPoolDefs
);
1342 // set an angle in the range from -90 to 90 degrees
1343 ScfTools::PutItem( rItemSet
, ScRotateValueItem( maApiData
.mnRotation
), bSkipPoolDefs
);
1345 ScfTools::PutItem( rItemSet
, ScVerticalStackCell( maApiData
.meOrientation
== css::table::CellOrientation_STACKED
), bSkipPoolDefs
);
1347 ScfTools::PutItem( rItemSet
, ScIndentItem( maApiData
.mnIndent
), bSkipPoolDefs
);
1349 ScfTools::PutItem( rItemSet
, ScLineBreakCell( maApiData
.mbWrapText
), bSkipPoolDefs
);
1350 ScfTools::PutItem( rItemSet
, ScShrinkToFitCell( maApiData
.mbShrink
), bSkipPoolDefs
);
1353 ProtectionModel::ProtectionModel() :
1354 mbLocked( true ), // default in Excel and Calc
1359 ApiProtectionData::ApiProtectionData() :
1360 maCellProt( true, false, false, false )
1364 bool operator==( const ApiProtectionData
& rLeft
, const ApiProtectionData
& rRight
)
1367 (rLeft
.maCellProt
.IsLocked
== rRight
.maCellProt
.IsLocked
) &&
1368 (rLeft
.maCellProt
.IsFormulaHidden
== rRight
.maCellProt
.IsFormulaHidden
) &&
1369 (rLeft
.maCellProt
.IsHidden
== rRight
.maCellProt
.IsHidden
) &&
1370 (rLeft
.maCellProt
.IsPrintHidden
== rRight
.maCellProt
.IsPrintHidden
);
1373 Protection::Protection( const WorkbookHelper
& rHelper
, bool bDxf
) :
1374 WorkbookHelper( rHelper
),
1379 void Protection::importProtection( const AttributeList
& rAttribs
)
1381 maModel
.mbLocked
= rAttribs
.getBool( XML_locked
, true );
1382 maModel
.mbHidden
= rAttribs
.getBool( XML_hidden
, false );
1385 void Protection::importDxfProtection( sal_Int32 nElement
, SequenceInputStream
& rStrm
)
1387 SAL_WARN_IF( !mbDxf
, "sc", "Protection::importDxfProtection - missing protection flag" );
1388 bool bFlag
= rStrm
.readuInt8() != 0;
1392 maModel
.mbLocked
= bFlag
;
1395 maModel
.mbHidden
= bFlag
;
1398 OSL_FAIL( "Protection::importDxfProtection - unexpected element identifier" );
1402 void Protection::setBiff12Data( sal_uInt32 nFlags
)
1404 maModel
.mbLocked
= getFlag( nFlags
, BIFF12_XF_LOCKED
);
1405 maModel
.mbHidden
= getFlag( nFlags
, BIFF12_XF_HIDDEN
);
1408 void Protection::finalizeImport()
1410 maApiData
.maCellProt
.IsLocked
= maModel
.mbLocked
;
1411 maApiData
.maCellProt
.IsFormulaHidden
= maModel
.mbHidden
;
1414 void Protection::fillToItemSet( SfxItemSet
& rItemSet
, bool bSkipPoolDefs
) const
1416 ScfTools::PutItem( rItemSet
, ScProtectionAttr( maApiData
.maCellProt
.IsLocked
, maApiData
.maCellProt
.IsFormulaHidden
), bSkipPoolDefs
);
1421 bool lcl_isBorder(const css::table::BorderLine
& rBorder
)
1423 return (rBorder
.InnerLineWidth
> 0) || (rBorder
.OuterLineWidth
> 0);
1428 BorderLineModel::BorderLineModel( bool bDxf
) :
1429 mnStyle( XML_none
),
1432 maColor
.setIndexed( OOX_COLOR_WINDOWTEXT
);
1435 void BorderLineModel::setBiffStyle( sal_Int32 nLineStyle
)
1437 static const sal_Int32 spnStyleIds
[] = {
1438 XML_none
, XML_thin
, XML_medium
, XML_dashed
,
1439 XML_dotted
, XML_thick
, XML_double
, XML_hair
,
1440 XML_mediumDashed
, XML_dashDot
, XML_mediumDashDot
, XML_dashDotDot
,
1441 XML_mediumDashDotDot
, XML_slantDashDot
};
1442 mnStyle
= STATIC_ARRAY_SELECT( spnStyleIds
, nLineStyle
, XML_none
);
1445 BorderModel::BorderModel( bool bDxf
) :
1451 mbDiagTLtoBR( false ),
1452 mbDiagBLtoTR( false )
1456 ApiBorderData::ApiBorderData() :
1457 mbBorderUsed( false ),
1462 bool ApiBorderData::hasAnyOuterBorder() const
1465 ( lcl_isBorder( maTop
) && maTop
.OuterLineWidth
> 0 ) ||
1466 ( lcl_isBorder( maBottom
) && maBottom
.OuterLineWidth
> 0 ) ||
1467 ( lcl_isBorder( maLeft
) && maLeft
.OuterLineWidth
> 0 ) ||
1468 ( lcl_isBorder( maRight
) && maRight
.OuterLineWidth
> 0 );
1473 void lclSetBorderLineWidth( BorderLine
& rBorderLine
,
1474 sal_Int16 nOuter
, sal_Int16 nDist
= API_LINE_NONE
, sal_Int16 nInner
= API_LINE_NONE
)
1476 rBorderLine
.OuterLineWidth
= nOuter
;
1477 rBorderLine
.LineDistance
= nDist
;
1478 rBorderLine
.InnerLineWidth
= nInner
;
1483 Border::Border( const WorkbookHelper
& rHelper
, bool bDxf
) :
1484 WorkbookHelper( rHelper
),
1490 void Border::importBorder( const AttributeList
& rAttribs
)
1492 maModel
.mbDiagTLtoBR
= rAttribs
.getBool( XML_diagonalDown
, false );
1493 maModel
.mbDiagBLtoTR
= rAttribs
.getBool( XML_diagonalUp
, false );
1496 void Border::importStyle( sal_Int32 nElement
, const AttributeList
& rAttribs
)
1498 if( BorderLineModel
* pBorderLine
= getBorderLine( nElement
) )
1500 pBorderLine
->mnStyle
= rAttribs
.getToken( XML_style
, XML_none
);
1501 pBorderLine
->mbUsed
= true;
1505 void Border::importColor( sal_Int32 nElement
, const AttributeList
& rAttribs
)
1507 if( BorderLineModel
* pBorderLine
= getBorderLine( nElement
) )
1508 pBorderLine
->maColor
.importColor( rAttribs
);
1511 void Border::importBorder( SequenceInputStream
& rStrm
)
1513 sal_uInt8 nFlags
= rStrm
.readuInt8();
1514 maModel
.mbDiagTLtoBR
= getFlag( nFlags
, BIFF12_BORDER_DIAG_TLBR
);
1515 maModel
.mbDiagBLtoTR
= getFlag( nFlags
, BIFF12_BORDER_DIAG_BLTR
);
1516 maModel
.maTop
.setBiffStyle( rStrm
.readuInt16() );
1517 rStrm
>> maModel
.maTop
.maColor
;
1518 maModel
.maBottom
.setBiffStyle( rStrm
.readuInt16() );
1519 rStrm
>> maModel
.maBottom
.maColor
;
1520 maModel
.maLeft
.setBiffStyle( rStrm
.readuInt16() );
1521 rStrm
>> maModel
.maLeft
.maColor
;
1522 maModel
.maRight
.setBiffStyle( rStrm
.readuInt16() );
1523 rStrm
>> maModel
.maRight
.maColor
;
1524 maModel
.maDiagonal
.setBiffStyle( rStrm
.readuInt16() );
1525 rStrm
>> maModel
.maDiagonal
.maColor
;
1528 void Border::importDxfBorder( sal_Int32 nElement
, SequenceInputStream
& rStrm
)
1530 SAL_WARN_IF( !mbDxf
, "sc", "Border::importDxfBorder - missing conditional formatting flag" );
1531 if( BorderLineModel
* pBorderLine
= getBorderLine( nElement
) )
1534 rStrm
>> pBorderLine
->maColor
;
1535 nStyle
= rStrm
.readuInt16();
1536 pBorderLine
->setBiffStyle( nStyle
);
1537 pBorderLine
->mbUsed
= true;
1541 void Border::finalizeImport( bool bRTL
)
1544 std::swap(maModel
.maLeft
, maModel
.maRight
);
1546 maApiData
.mbBorderUsed
= maModel
.maLeft
.mbUsed
|| maModel
.maRight
.mbUsed
|| maModel
.maTop
.mbUsed
|| maModel
.maBottom
.mbUsed
;
1547 maApiData
.mbDiagUsed
= maModel
.maDiagonal
.mbUsed
;
1549 convertBorderLine( maApiData
.maLeft
, maModel
.maLeft
);
1550 convertBorderLine( maApiData
.maRight
, maModel
.maRight
);
1551 convertBorderLine( maApiData
.maTop
, maModel
.maTop
);
1552 convertBorderLine( maApiData
.maBottom
, maModel
.maBottom
);
1554 maApiData
.maComplexColorLeft
= maModel
.maLeft
.maColor
.createComplexColor(getBaseFilter().getGraphicHelper(), -1);
1555 maApiData
.maComplexColorRight
= maModel
.maRight
.maColor
.createComplexColor(getBaseFilter().getGraphicHelper(), -1);
1556 maApiData
.maComplexColorTop
= maModel
.maTop
.maColor
.createComplexColor(getBaseFilter().getGraphicHelper(), -1);
1557 maApiData
.maComplexColorBottom
= maModel
.maBottom
.maColor
.createComplexColor(getBaseFilter().getGraphicHelper(), -1);
1559 if( maModel
.mbDiagTLtoBR
)
1560 convertBorderLine( maApiData
.maTLtoBR
, maModel
.maDiagonal
);
1561 if( maModel
.mbDiagBLtoTR
)
1562 convertBorderLine( maApiData
.maBLtoTR
, maModel
.maDiagonal
);
1565 void Border::fillToItemSet( SfxItemSet
& rItemSet
, bool bSkipPoolDefs
) const
1567 if( maApiData
.mbBorderUsed
)
1569 SvxBoxItem
aBoxItem( ATTR_BORDER
);
1570 editeng::SvxBorderLine aLine
;
1572 if (SvxBoxItem::LineToSvxLine(maApiData
.maLeft
, aLine
, false))
1574 aLine
.setComplexColor(maApiData
.maComplexColorLeft
);
1575 aBoxItem
.SetLine( &aLine
, SvxBoxItemLine::LEFT
);
1577 if (SvxBoxItem::LineToSvxLine(maApiData
.maRight
, aLine
, false))
1579 aLine
.setComplexColor(maApiData
.maComplexColorRight
);
1580 aBoxItem
.SetLine( &aLine
, SvxBoxItemLine::RIGHT
);
1582 if (SvxBoxItem::LineToSvxLine(maApiData
.maTop
, aLine
, false))
1584 aLine
.setComplexColor(maApiData
.maComplexColorTop
);
1585 aBoxItem
.SetLine( &aLine
, SvxBoxItemLine::TOP
);
1587 if (SvxBoxItem::LineToSvxLine(maApiData
.maBottom
, aLine
, false))
1589 aLine
.setComplexColor(maApiData
.maComplexColorBottom
);
1590 aBoxItem
.SetLine( &aLine
, SvxBoxItemLine::BOTTOM
);
1592 ScfTools::PutItem( rItemSet
, aBoxItem
, bSkipPoolDefs
);
1594 if ( !maApiData
.mbDiagUsed
)
1597 SvxLineItem
aTLBRItem( ATTR_BORDER_TLBR
);
1598 SvxLineItem
aBLTRItem( ATTR_BORDER_BLTR
);
1599 ::editeng::SvxBorderLine aLine
;
1600 if (SvxBoxItem::LineToSvxLine(maApiData
.maTLtoBR
, aLine
, false))
1602 aTLBRItem
.SetLine( &aLine
);
1604 if (SvxBoxItem::LineToSvxLine(maApiData
.maBLtoTR
, aLine
, false))
1606 aBLTRItem
.SetLine( &aLine
);
1608 ScfTools::PutItem( rItemSet
, aTLBRItem
, bSkipPoolDefs
);
1609 ScfTools::PutItem( rItemSet
, aBLTRItem
, bSkipPoolDefs
);
1612 BorderLineModel
* Border::getBorderLine( sal_Int32 nElement
)
1616 case XLS_TOKEN( left
): return &maModel
.maLeft
;
1617 case XLS_TOKEN( start
): return &maModel
.maLeft
;
1618 case XLS_TOKEN( right
): return &maModel
.maRight
;
1619 case XLS_TOKEN( end
): return &maModel
.maRight
;
1620 case XLS_TOKEN( top
): return &maModel
.maTop
;
1621 case XLS_TOKEN( bottom
): return &maModel
.maBottom
;
1622 case XLS_TOKEN( diagonal
): return &maModel
.maDiagonal
;
1627 bool Border::convertBorderLine( BorderLine2
& rBorderLine
, const BorderLineModel
& rModel
)
1629 // Document: sc/qa/unit/data/README.cellborders
1631 rBorderLine
.Color
= sal_Int32(rModel
.maColor
.getColor( getBaseFilter().getGraphicHelper(), API_RGB_BLACK
));
1632 switch( rModel
.mnStyle
)
1635 lclSetBorderLineWidth( rBorderLine
, API_LINE_THIN
);
1636 rBorderLine
.LineStyle
= BorderLineStyle::DASH_DOT
;
1638 case XML_dashDotDot
:
1639 lclSetBorderLineWidth( rBorderLine
, API_LINE_THIN
);
1640 rBorderLine
.LineStyle
= BorderLineStyle::DASH_DOT_DOT
;
1643 lclSetBorderLineWidth( rBorderLine
, API_LINE_THIN
);
1644 rBorderLine
.LineStyle
= BorderLineStyle::FINE_DASHED
;
1647 lclSetBorderLineWidth( rBorderLine
, API_LINE_THIN
);
1648 rBorderLine
.LineStyle
= BorderLineStyle::DOTTED
;
1651 lclSetBorderLineWidth( rBorderLine
, 10, 15, 10 );
1652 rBorderLine
.LineStyle
= BorderLineStyle::DOUBLE_THIN
;
1654 case XML_hair
: lclSetBorderLineWidth( rBorderLine
, API_LINE_HAIR
); break;
1655 case XML_medium
: lclSetBorderLineWidth( rBorderLine
, API_LINE_MEDIUM
); break;
1656 case XML_mediumDashDot
:
1657 lclSetBorderLineWidth( rBorderLine
, API_LINE_MEDIUM
);
1658 rBorderLine
.LineStyle
= BorderLineStyle::DASH_DOT
;
1660 case XML_mediumDashDotDot
:
1661 lclSetBorderLineWidth( rBorderLine
, API_LINE_MEDIUM
);
1662 rBorderLine
.LineStyle
= BorderLineStyle::DASH_DOT_DOT
;
1664 case XML_mediumDashed
:
1665 lclSetBorderLineWidth( rBorderLine
, API_LINE_MEDIUM
);
1666 rBorderLine
.LineStyle
= BorderLineStyle::DASHED
;
1668 case XML_none
: lclSetBorderLineWidth( rBorderLine
, API_LINE_NONE
); break;
1669 case XML_slantDashDot
:
1670 lclSetBorderLineWidth( rBorderLine
, API_LINE_MEDIUM
);
1671 rBorderLine
.LineStyle
= BorderLineStyle::FINE_DASHED
;
1673 case XML_thick
: lclSetBorderLineWidth( rBorderLine
, API_LINE_THICK
); break;
1674 case XML_thin
: lclSetBorderLineWidth( rBorderLine
, API_LINE_THIN
); break;
1675 default: lclSetBorderLineWidth( rBorderLine
, API_LINE_NONE
); break;
1677 return rModel
.mbUsed
;
1680 PatternFillModel::PatternFillModel( bool bDxf
) :
1681 mnPattern( XML_none
),
1682 mbPattColorUsed( !bDxf
),
1683 mbFillColorUsed( !bDxf
),
1684 mbPatternUsed( !bDxf
)
1686 maPatternColor
.setIndexed( OOX_COLOR_WINDOWTEXT
);
1687 maFilterPatternColor
.setIndexed( OOX_COLOR_WINDOWTEXT
);
1688 maFillColor
.setIndexed( OOX_COLOR_WINDOWBACK
);
1691 void PatternFillModel::setBiffPattern( sal_Int32 nPattern
)
1693 static const sal_Int32 spnPatternIds
[] = {
1694 XML_none
, XML_solid
, XML_mediumGray
, XML_darkGray
,
1695 XML_lightGray
, XML_darkHorizontal
, XML_darkVertical
, XML_darkDown
,
1696 XML_darkUp
, XML_darkGrid
, XML_darkTrellis
, XML_lightHorizontal
,
1697 XML_lightVertical
, XML_lightDown
, XML_lightUp
, XML_lightGrid
,
1698 XML_lightTrellis
, XML_gray125
, XML_gray0625
};
1699 mnPattern
= STATIC_ARRAY_SELECT( spnPatternIds
, nPattern
, XML_none
);
1702 GradientFillModel::GradientFillModel() :
1703 mnType( XML_linear
),
1712 void GradientFillModel::readGradient( SequenceInputStream
& rStrm
)
1715 nType
= rStrm
.readInt32();
1716 mfAngle
= rStrm
.readDouble();
1717 mfLeft
= rStrm
.readDouble();
1718 mfRight
= rStrm
.readDouble();
1719 mfTop
= rStrm
.readDouble();
1720 mfBottom
= rStrm
.readDouble();
1721 static const sal_Int32 spnTypes
[] = { XML_linear
, XML_path
};
1722 mnType
= STATIC_ARRAY_SELECT( spnTypes
, nType
, XML_TOKEN_INVALID
);
1725 void GradientFillModel::readGradientStop( SequenceInputStream
& rStrm
, bool bDxf
)
1732 fPosition
= rStrm
.readDouble();
1738 fPosition
= rStrm
.readDouble();
1740 if( !rStrm
.isEof() && (fPosition
>= 0.0) )
1741 maColors
[ fPosition
] = std::move(aColor
);
1744 ApiSolidFillData::ApiSolidFillData() :
1745 mnColor( API_RGB_TRANSPARENT
),
1746 mnFilterColor( API_RGB_TRANSPARENT
),
1747 mbTransparent( true ),
1754 sal_Int32
lclGetMixedColorComp( sal_Int32 nPatt
, sal_Int32 nFill
, sal_Int32 nAlpha
)
1756 return ((nPatt
- nFill
) * nAlpha
) / 0x80 + nFill
;
1759 ::Color
lclGetMixedColor( ::Color nPattColor
, ::Color nFillColor
, sal_Int32 nAlpha
)
1762 lclGetMixedColorComp( nPattColor
.GetRed(), nFillColor
.GetRed(), nAlpha
),
1763 lclGetMixedColorComp( nPattColor
.GetGreen(), nFillColor
.GetGreen(), nAlpha
),
1764 lclGetMixedColorComp( nPattColor
.GetBlue(), nFillColor
.GetBlue(), nAlpha
) );
1769 Fill::Fill( const WorkbookHelper
& rHelper
, bool bDxf
) :
1770 WorkbookHelper( rHelper
),
1775 void Fill::importPatternFill( const AttributeList
& rAttribs
)
1777 mxPatternModel
= std::make_shared
<PatternFillModel
>( mbDxf
);
1778 mxPatternModel
->mnPattern
= rAttribs
.getToken( XML_patternType
, XML_none
);
1780 mxPatternModel
->mbPatternUsed
= rAttribs
.hasAttribute( XML_patternType
);
1783 void Fill::importFgColor( const AttributeList
& rAttribs
)
1785 OSL_ENSURE( mxPatternModel
, "Fill::importFgColor - missing pattern data" );
1786 if( mxPatternModel
)
1788 mxPatternModel
->maPatternColor
.importColor(rAttribs
);
1789 mxPatternModel
->mbPattColorUsed
= true;
1793 void Fill::importBgColor( const AttributeList
& rAttribs
)
1795 OSL_ENSURE( mxPatternModel
, "Fill::importBgColor - missing pattern data" );
1796 if( mxPatternModel
)
1798 mxPatternModel
->maFillColor
.importColor(rAttribs
);
1799 mxPatternModel
->mbFillColorUsed
= true;
1803 void Fill::importGradientFill( const AttributeList
& rAttribs
)
1805 mxGradientModel
= std::make_shared
<GradientFillModel
>();
1806 mxGradientModel
->mnType
= rAttribs
.getToken( XML_type
, XML_linear
);
1807 mxGradientModel
->mfAngle
= rAttribs
.getDouble( XML_degree
, 0.0 );
1808 mxGradientModel
->mfLeft
= rAttribs
.getDouble( XML_left
, 0.0 );
1809 mxGradientModel
->mfRight
= rAttribs
.getDouble( XML_right
, 0.0 );
1810 mxGradientModel
->mfTop
= rAttribs
.getDouble( XML_top
, 0.0 );
1811 mxGradientModel
->mfBottom
= rAttribs
.getDouble( XML_bottom
, 0.0 );
1814 void Fill::importColor( const AttributeList
& rAttribs
, double fPosition
)
1816 OSL_ENSURE( mxGradientModel
, "Fill::importColor - missing gradient data" );
1817 if( mxGradientModel
&& (fPosition
>= 0.0) )
1818 mxGradientModel
->maColors
[ fPosition
].importColor( rAttribs
);
1821 void Fill::importFill( SequenceInputStream
& rStrm
)
1823 SAL_WARN_IF( mbDxf
, "sc", "Fill::importFill - unexpected conditional formatting flag" );
1824 sal_Int32 nPattern
= rStrm
.readInt32();
1825 if( nPattern
== BIFF12_FILL_GRADIENT
)
1827 mxGradientModel
= std::make_shared
<GradientFillModel
>();
1828 sal_Int32 nStopCount
;
1830 mxGradientModel
->readGradient( rStrm
);
1831 nStopCount
= rStrm
.readInt32();
1832 for( sal_Int32 nStop
= 0; (nStop
< nStopCount
) && !rStrm
.isEof(); ++nStop
)
1833 mxGradientModel
->readGradientStop( rStrm
, false );
1837 mxPatternModel
= std::make_shared
<PatternFillModel
>( mbDxf
);
1838 mxPatternModel
->setBiffPattern( nPattern
);
1839 rStrm
>> mxPatternModel
->maPatternColor
>> mxPatternModel
->maFillColor
;
1843 void Fill::importDxfPattern( SequenceInputStream
& rStrm
)
1845 SAL_WARN_IF( !mbDxf
, "sc", "Fill::importDxfPattern - missing conditional formatting flag" );
1846 if( !mxPatternModel
)
1847 mxPatternModel
= std::make_shared
<PatternFillModel
>( mbDxf
);
1848 mxPatternModel
->setBiffPattern( rStrm
.readuInt8() );
1849 mxPatternModel
->mbPatternUsed
= true;
1852 void Fill::importDxfFgColor( SequenceInputStream
& rStrm
)
1854 SAL_WARN_IF( !mbDxf
, "sc", "Fill::importDxfFgColor - missing conditional formatting flag" );
1855 if( !mxPatternModel
)
1856 mxPatternModel
= std::make_shared
<PatternFillModel
>( mbDxf
);
1857 mxPatternModel
->maPatternColor
.importColor( rStrm
);
1858 mxPatternModel
->mbPattColorUsed
= true;
1861 void Fill::importDxfBgColor( SequenceInputStream
& rStrm
)
1863 SAL_WARN_IF( !mbDxf
, "sc", "Fill::importDxfBgColor - missing conditional formatting flag" );
1864 if( !mxPatternModel
)
1865 mxPatternModel
= std::make_shared
<PatternFillModel
>( mbDxf
);
1866 mxPatternModel
->maFillColor
.importColor( rStrm
);
1867 mxPatternModel
->mbFillColorUsed
= true;
1870 void Fill::importDxfGradient( SequenceInputStream
& rStrm
)
1872 SAL_WARN_IF( !mbDxf
, "sc", "Fill::importDxfGradient - missing conditional formatting flag" );
1873 if( !mxGradientModel
)
1874 mxGradientModel
= std::make_shared
<GradientFillModel
>();
1875 mxGradientModel
->readGradient( rStrm
);
1878 void Fill::importDxfStop( SequenceInputStream
& rStrm
)
1880 SAL_WARN_IF( !mbDxf
, "sc", "Fill::importDxfStop - missing conditional formatting flag" );
1881 if( !mxGradientModel
)
1882 mxGradientModel
= std::make_shared
<GradientFillModel
>();
1883 mxGradientModel
->readGradientStop( rStrm
, true );
1886 void Fill::finalizeImport()
1888 const GraphicHelper
& rGraphicHelper
= getBaseFilter().getGraphicHelper();
1890 if( mxPatternModel
)
1892 // finalize the OOXML data struct
1893 PatternFillModel
& rModel
= *mxPatternModel
;
1896 if( rModel
.mbFillColorUsed
&& (!rModel
.mbPatternUsed
|| (rModel
.mnPattern
== XML_solid
)) )
1898 rModel
.maFilterPatternColor
= rModel
.maPatternColor
;
1899 rModel
.maPatternColor
= rModel
.maFillColor
;
1900 rModel
.mnPattern
= XML_solid
;
1901 rModel
.mbPattColorUsed
= rModel
.mbPatternUsed
= true;
1904 !rModel
.mbFillColorUsed
&& !rModel
.mbPattColorUsed
&&
1905 rModel
.mbPatternUsed
&& rModel
.mnPattern
== XML_solid
)
1907 rModel
.mbPatternUsed
= false;
1910 rModel
.maFilterPatternColor
= rModel
.maPatternColor
;
1913 // convert to API fill settings
1914 maApiData
.mbUsed
= rModel
.mbPatternUsed
;
1915 if( rModel
.mnPattern
== XML_none
)
1917 maApiData
.mnColor
= API_RGB_TRANSPARENT
;
1918 maApiData
.mbTransparent
= true;
1922 sal_Int32 nAlpha
= 0x80;
1923 switch( rModel
.mnPattern
)
1925 case XML_darkDown
: nAlpha
= 0x40; break;
1926 case XML_darkGray
: nAlpha
= 0x60; break;
1927 case XML_darkGrid
: nAlpha
= 0x40; break;
1928 case XML_darkHorizontal
: nAlpha
= 0x40; break;
1929 case XML_darkTrellis
: nAlpha
= 0x60; break;
1930 case XML_darkUp
: nAlpha
= 0x40; break;
1931 case XML_darkVertical
: nAlpha
= 0x40; break;
1932 case XML_gray0625
: nAlpha
= 0x08; break;
1933 case XML_gray125
: nAlpha
= 0x10; break;
1934 case XML_lightDown
: nAlpha
= 0x20; break;
1935 case XML_lightGray
: nAlpha
= 0x20; break;
1936 case XML_lightGrid
: nAlpha
= 0x38; break;
1937 case XML_lightHorizontal
: nAlpha
= 0x20; break;
1938 case XML_lightTrellis
: nAlpha
= 0x30; break;
1939 case XML_lightUp
: nAlpha
= 0x20; break;
1940 case XML_lightVertical
: nAlpha
= 0x20; break;
1941 case XML_mediumGray
: nAlpha
= 0x40; break;
1942 case XML_solid
: nAlpha
= 0x80; break;
1945 ::Color nWinTextColor
= rGraphicHelper
.getSystemColor( XML_windowText
);
1946 ::Color nWinColor
= rGraphicHelper
.getSystemColor( XML_window
);
1948 if (!rModel
.mbPattColorUsed
)
1950 rModel
.maPatternColor
.setAuto();
1951 rModel
.maFilterPatternColor
.setAuto();
1953 ::Color nPattColor
= rModel
.maPatternColor
.getColor( rGraphicHelper
, nWinTextColor
);
1954 ::Color nFiltPattColor
= rModel
.maFilterPatternColor
.getColor( rGraphicHelper
, nWinTextColor
);
1956 if( !rModel
.mbFillColorUsed
)
1957 rModel
.maFillColor
.setAuto();
1958 ::Color nFillColor
= rModel
.maFillColor
.getColor( rGraphicHelper
, nWinColor
);
1960 maApiData
.mnColor
= lclGetMixedColor( nPattColor
, nFillColor
, nAlpha
);
1961 maApiData
.maComplexColor
= rModel
.maPatternColor
.createComplexColor(rGraphicHelper
, -1);
1962 maApiData
.mnFilterColor
= lclGetMixedColor( nFiltPattColor
, nFillColor
, nAlpha
);
1963 maApiData
.mbTransparent
= false;
1966 else if( mxGradientModel
&& !mxGradientModel
->maColors
.empty() )
1968 GradientFillModel
& rModel
= *mxGradientModel
;
1969 maApiData
.mbUsed
= true; // no support for differential attributes
1970 GradientFillModel::ColorMap::const_iterator aIt
= rModel
.maColors
.begin();
1971 OSL_ENSURE( !aIt
->second
.isAuto(), "Fill::finalizeImport - automatic gradient color" );
1972 maApiData
.mnColor
= aIt
->second
.getColor( rGraphicHelper
, API_RGB_WHITE
);
1973 if( ++aIt
!= rModel
.maColors
.end() )
1975 OSL_ENSURE( !aIt
->second
.isAuto(), "Fill::finalizeImport - automatic gradient color" );
1976 ::Color nEndColor
= aIt
->second
.getColor( rGraphicHelper
, API_RGB_WHITE
);
1977 maApiData
.mnColor
= lclGetMixedColor( maApiData
.mnColor
, nEndColor
, 0x40 );
1978 maApiData
.mbTransparent
= false;
1983 void Fill::fillToItemSet( SfxItemSet
& rItemSet
, bool bSkipPoolDefs
) const
1985 if( !maApiData
.mbUsed
)
1988 SvxBrushItem
aBrushItem( ATTR_BACKGROUND
);
1989 if ( maApiData
.mbTransparent
)
1991 aBrushItem
.SetColor( COL_TRANSPARENT
);
1992 aBrushItem
.SetFiltColor( COL_TRANSPARENT
);
1996 aBrushItem
.SetColor( maApiData
.mnColor
);
1997 aBrushItem
.setComplexColor(maApiData
.maComplexColor
);
1998 aBrushItem
.SetFiltColor( maApiData
.mnFilterColor
);
2000 ScfTools::PutItem( rItemSet
, aBrushItem
, bSkipPoolDefs
);
2003 XfModel::XfModel() :
2010 mbFontUsed( false ),
2011 mbNumFmtUsed( false ),
2012 mbAlignUsed( false ),
2013 mbProtUsed( false ),
2014 mbBorderUsed( false ),
2019 Xf::AttrList::AttrList(const ScPatternAttr
* pDefPattern
):
2020 mbLatinNumFmtOnly(true),
2021 mpDefPattern(pDefPattern
)
2024 Xf::Xf( const WorkbookHelper
& rHelper
) :
2025 WorkbookHelper( rHelper
),
2027 maAlignment( rHelper
),
2028 maProtection( rHelper
, false ),
2029 meRotationRef( css::table::CellVertJustify2::STANDARD
),
2030 mpStyleSheet( nullptr )
2034 void Xf::importXf( const AttributeList
& rAttribs
, bool bCellXf
)
2036 maModel
.mbCellXf
= bCellXf
;
2037 // tdf#70565 Set proper default value to "0" of xfId attribute
2038 // When xfId is not exist during .xlsx import
2039 // it must have values set to "0".
2040 // This doesn't impact spreadsheets created with MS Excel,
2041 // as xfId attribute is always created during export to .xlsx
2042 // Not setting "0" value is causing wrong .xlsx import by LibreOffice,
2043 // for spreadsheets created by external applications (ex. SAP BI).
2045 if ( maModel
.mbCellXf
)
2047 const sal_Int32 xfId
= rAttribs
.getInteger( XML_xfId
, -1 );
2048 // No xfId => no cellStyleXfs that could overwrite this on change, thus
2049 // has to be applied.
2050 bApplyDefault
= (xfId
< 0);
2051 maModel
.mnStyleXfId
= std::max
<sal_Int32
>(0, xfId
);
2055 maModel
.mnStyleXfId
= rAttribs
.getInteger( XML_xfId
, -1 );
2056 bApplyDefault
= true;
2058 maModel
.mnFontId
= rAttribs
.getInteger( XML_fontId
, -1 );
2059 maModel
.mnNumFmtId
= rAttribs
.getInteger( XML_numFmtId
, -1 );
2060 maModel
.mnBorderId
= rAttribs
.getInteger( XML_borderId
, -1 );
2061 maModel
.mnFillId
= rAttribs
.getInteger( XML_fillId
, -1 );
2063 // Default value of the apply*** attributes is dependent on context:
2064 // true in cellStyleXfs element, false in cellXfs element...
2065 // But it's not as easy as it sounds, for docs see
2066 // https://learn.microsoft.com/en-us/openspecs/office_standards/ms-oe376/59922f8b-0edc-4e93-a822-9f22254aec46
2067 // and apparently in reality cellStyleXfs xf and cellXfs xf are not merged
2069 // https://learn.microsoft.com/en-us/openspecs/office_standards/ms-oe376/bcf98682-e8d3-44b8-b8f8-0bf696878ba1
2070 // "b. The standard states that both the cell style xf records and cell xf
2071 // records must be read to understand the full set of formatting applied to
2073 // "In Office, only the cell xf record defines the formatting applied to a cell."
2075 // So for reading documents this is all crap and effectively xf records
2076 // apply their explicit properties by default unless denied.
2077 // bApplyDefault==false only for cellXf xf with xfId.
2079 // For cellXf xf, mbAlignUsed and mbProtUsed will be set when actually
2080 // importing the element.
2081 maModel
.mbAlignUsed
= rAttribs
.getBool( XML_applyAlignment
, bApplyDefault
);
2082 maModel
.mbProtUsed
= rAttribs
.getBool( XML_applyProtection
, bApplyDefault
);
2084 maModel
.mbFontUsed
= rAttribs
.getBool( XML_applyFont
, bApplyDefault
|| maModel
.mnFontId
> 0);
2085 maModel
.mbNumFmtUsed
= rAttribs
.getBool( XML_applyNumberFormat
, bApplyDefault
|| maModel
.mnNumFmtId
> 0);
2086 maModel
.mbBorderUsed
= rAttribs
.getBool( XML_applyBorder
, bApplyDefault
|| maModel
.mnBorderId
> 0);
2087 maModel
.mbAreaUsed
= rAttribs
.getBool( XML_applyFill
, bApplyDefault
|| maModel
.mnFillId
> 0);
2090 void Xf::importAlignment( const AttributeList
& rAttribs
)
2092 maAlignment
.importAlignment( rAttribs
);
2093 if (maModel
.mbCellXf
)
2094 maModel
.mbAlignUsed
= true;
2097 void Xf::importProtection( const AttributeList
& rAttribs
)
2099 maProtection
.importProtection( rAttribs
);
2100 if (maModel
.mbCellXf
)
2101 maModel
.mbProtUsed
= true;
2104 void Xf::importXf( SequenceInputStream
& rStrm
, bool bCellXf
)
2106 maModel
.mbCellXf
= bCellXf
;
2107 maModel
.mnStyleXfId
= rStrm
.readuInt16();
2108 maModel
.mnNumFmtId
= rStrm
.readuInt16();
2109 maModel
.mnFontId
= rStrm
.readuInt16();
2110 maModel
.mnFillId
= rStrm
.readuInt16();
2111 maModel
.mnBorderId
= rStrm
.readuInt16();
2112 sal_uInt32 nFlags
= rStrm
.readuInt32();
2113 maAlignment
.setBiff12Data( nFlags
);
2114 maProtection
.setBiff12Data( nFlags
);
2115 // used flags, see comments in Xf::setBiffUsedFlags()
2116 sal_uInt16 nUsedFlags
= rStrm
.readuInt16();
2117 maModel
.mbFontUsed
= maModel
.mbCellXf
== getFlag( nUsedFlags
, BIFF12_XF_FONT_USED
);
2118 maModel
.mbNumFmtUsed
= maModel
.mbCellXf
== getFlag( nUsedFlags
, BIFF12_XF_NUMFMT_USED
);
2119 maModel
.mbAlignUsed
= maModel
.mbCellXf
== getFlag( nUsedFlags
, BIFF12_XF_ALIGN_USED
);
2120 maModel
.mbProtUsed
= maModel
.mbCellXf
== getFlag( nUsedFlags
, BIFF12_XF_PROT_USED
);
2121 maModel
.mbBorderUsed
= maModel
.mbCellXf
== getFlag( nUsedFlags
, BIFF12_XF_BORDER_USED
);
2122 maModel
.mbAreaUsed
= maModel
.mbCellXf
== getFlag( nUsedFlags
, BIFF12_XF_AREA_USED
);
2125 void Xf::finalizeImport()
2127 // alignment and protection
2128 maAlignment
.finalizeImport();
2129 maProtection
.finalizeImport();
2132 FontRef
Xf::getFont() const
2134 return getStyles().getFont( maModel
.mnFontId
);
2137 void Xf::applyPatternToAttrList( AttrList
& rAttrs
, SCROW nRow1
, SCROW nRow2
, sal_Int32 nXfId
, sal_Int32 nNumFmtId
, ScPatternCache
& rCache
)
2139 ScPatternAttr
* pCachedPattern
= rCache
.query(nXfId
, nNumFmtId
);
2140 if (!pCachedPattern
)
2143 ScPatternAttr
& rPat
= pCachedPattern
? *pCachedPattern
: *mpPattern
;
2144 ScDocumentImport
& rDocImport
= getDocImport();
2145 ScDocument
& rDoc
= getScDocument();
2146 if ( !pCachedPattern
&& isCellXf() )
2148 StylesBuffer
& rStyles
= getStyles();
2149 rStyles
.createCellStyle( maModel
.mnStyleXfId
);
2151 mpStyleSheet
= rStyles
.getCellStyleSheet( maModel
.mnStyleXfId
);
2154 //rDoc.ApplySelectionStyle( static_cast<ScStyleSheet&>(*mpStyleSheet), rMarkData );
2155 rPat
.SetStyleSheet(mpStyleSheet
, false);
2159 ScStyleSheetPool
* pStylePool
= rDoc
.GetStyleSheetPool();
2162 ScStyleSheet
* pStyleSheet
= static_cast<ScStyleSheet
*>(
2164 ScResId(STR_STYLENAME_STANDARD
), SfxStyleFamily::Para
));
2167 rPat
.SetStyleSheet( pStyleSheet
, false );
2171 if ( !pCachedPattern
&& nNumFmtId
>= 0 )
2173 ScPatternAttr
aNumPat(rDoc
.getCellAttributeHelper());
2174 mnScNumFmt
= getStyles().writeNumFmtToItemSet( aNumPat
.GetItemSet(), nNumFmtId
, false );
2175 rPat
.GetItemSet().Put(aNumPat
.GetItemSet());
2178 if (!pCachedPattern
&& !rDocImport
.isLatinScript(mnScNumFmt
))
2179 rAttrs
.mbLatinNumFmtOnly
= false;
2181 if (!pCachedPattern
&& !rPat
.GetStyleName())
2185 // Check for a gap between the last entry and this one.
2186 bool bHasGap
= false;
2187 if (rAttrs
.maAttrs
.empty() && nRow1
> 0)
2188 // First attribute range doesn't start at row 0.
2191 if (!rAttrs
.maAttrs
.empty() && rAttrs
.maAttrs
.back().nEndRow
+ 1 < nRow1
)
2196 // Fill this gap with the default pattern.
2198 aEntry
.nEndRow
= nRow1
- 1;
2199 aEntry
.setScPatternAttr(rAttrs
.mpDefPattern
, false);
2200 rAttrs
.maAttrs
.push_back(aEntry
);
2202 // Check if the default pattern is 'General'.
2203 if (!rDocImport
.isLatinScript(*aEntry
.getScPatternAttr()))
2204 rAttrs
.mbLatinNumFmtOnly
= false;
2208 aEntry
.nEndRow
= nRow2
;
2209 aEntry
.setScPatternAttr(&rPat
, false);
2210 // Put the allocated pattern to cache
2211 if (!pCachedPattern
)
2212 rCache
.add(nXfId
, nNumFmtId
, const_cast<ScPatternAttr
*>(aEntry
.getScPatternAttr()));
2214 rAttrs
.maAttrs
.push_back(aEntry
);
2216 if (!rDocImport
.isLatinScript(*aEntry
.getScPatternAttr()))
2217 rAttrs
.mbLatinNumFmtOnly
= false;
2220 void Xf::writeToDoc( ScDocumentImport
& rDoc
, const ScRange
& rRange
)
2222 const StylesBuffer
& rStyles
= getStyles();
2227 OUString aStyleName
= rStyles
.createCellStyle(maModel
.mnStyleXfId
);
2229 ScStyleSheet
* pStyleSheet
=
2230 static_cast<ScStyleSheet
*>(
2231 rDoc
.getDoc().GetStyleSheetPool()->Find(aStyleName
, SfxStyleFamily::Para
));
2235 rDoc
.getDoc().ApplyStyleAreaTab(
2236 rRange
.aStart
.Col(), rRange
.aStart
.Row(), rRange
.aEnd
.Col(), rRange
.aEnd
.Row(), rRange
.aStart
.Tab(),
2241 const ScPatternAttr
& rAttr
= createPattern();
2242 rDoc
.getDoc().ApplyPatternAreaTab(
2243 rRange
.aStart
.Col(), rRange
.aStart
.Row(), rRange
.aEnd
.Col(), rRange
.aEnd
.Row(), rRange
.aStart
.Tab(), rAttr
);
2246 const ::ScPatternAttr
&
2247 Xf::createPattern( bool bSkipPoolDefs
)
2251 mpPattern
.reset( new ::ScPatternAttr(getScDocument().getCellAttributeHelper()) );
2252 SfxItemSet
& rItemSet
= mpPattern
->GetItemSet();
2253 /* Enables the used flags, if the formatting attributes differ from the
2254 style XF. In cell XFs Excel uses the cell attributes, if they differ
2255 from the parent style XF (even if the used flag is switched off).
2256 #109899# ...or if the respective flag is not set in parent style XF.
2258 StylesBuffer
& rStyles
= getStyles();
2260 const Xf
* pStyleXf
= isCellXf() ? rStyles
.getStyleXf( maModel
.mnStyleXfId
).get() : nullptr;
2261 if( pStyleXf
&& !mpStyleSheet
)
2263 rStyles
.createCellStyle( maModel
.mnStyleXfId
);
2264 mpStyleSheet
= rStyles
.getCellStyleSheet( maModel
.mnStyleXfId
);
2265 OSL_ENSURE( mpStyleSheet
, "Xf::createPattern - no parentStyle created" );
2267 const XfModel
& rStyleData
= pStyleXf
->maModel
;
2268 if( !maModel
.mbFontUsed
)
2269 maModel
.mbFontUsed
= !rStyleData
.mbFontUsed
|| (maModel
.mnFontId
!= rStyleData
.mnFontId
);
2270 if( !maModel
.mbNumFmtUsed
)
2271 maModel
.mbNumFmtUsed
= !rStyleData
.mbNumFmtUsed
|| (maModel
.mnNumFmtId
!= rStyleData
.mnNumFmtId
);
2272 if( !maModel
.mbAlignUsed
)
2273 maModel
.mbAlignUsed
= !rStyleData
.mbAlignUsed
|| !(maAlignment
.getApiData() == pStyleXf
->maAlignment
.getApiData());
2274 if( !maModel
.mbProtUsed
)
2275 maModel
.mbProtUsed
= !rStyleData
.mbProtUsed
|| !(maProtection
.getApiData() == pStyleXf
->maProtection
.getApiData());
2276 if( !maModel
.mbBorderUsed
)
2277 maModel
.mbBorderUsed
= !rStyleData
.mbBorderUsed
|| !StylesBuffer::equalBorders( maModel
.mnBorderId
, rStyleData
.mnBorderId
);
2278 if( !maModel
.mbAreaUsed
)
2279 maModel
.mbAreaUsed
= !rStyleData
.mbAreaUsed
|| !StylesBuffer::equalFills( maModel
.mnFillId
, rStyleData
.mnFillId
);
2282 if( maModel
.mbProtUsed
)
2284 maProtection
.fillToItemSet( rItemSet
, bSkipPoolDefs
);
2288 if( maModel
.mbFontUsed
)
2290 rStyles
.writeFontToItemSet( rItemSet
, maModel
.mnFontId
, bSkipPoolDefs
);
2294 if( maModel
.mbNumFmtUsed
)
2296 mnScNumFmt
= rStyles
.writeNumFmtToItemSet( rItemSet
, maModel
.mnNumFmtId
, bSkipPoolDefs
);
2299 if( maModel
.mbAlignUsed
)
2301 maAlignment
.fillToItemSet( rItemSet
, bSkipPoolDefs
);
2305 if( maModel
.mbBorderUsed
)
2307 rStyles
.writeBorderToItemSet( rItemSet
, maModel
.mnBorderId
, bSkipPoolDefs
);
2311 if( maModel
.mbAreaUsed
)
2313 rStyles
.writeFillToItemSet( rItemSet
, maModel
.mnFillId
, bSkipPoolDefs
);
2316 /* #i38709# Decide which rotation reference mode to use. If any outer
2317 border line of the cell is set (either explicitly or via cell style),
2318 and the cell contents are rotated, set rotation reference to bottom of
2319 cell. This causes the borders to be painted rotated with the text. */
2320 if( const Alignment
* pAlignment
= maModel
.mbAlignUsed
? &maAlignment
: (pStyleXf
? &pStyleXf
->maAlignment
: nullptr) )
2322 SvxRotateMode eRotateMode
= SVX_ROTATE_MODE_STANDARD
;
2323 sal_Int32 nBorderId
= maModel
.mbBorderUsed
? maModel
.mnBorderId
: (pStyleXf
? pStyleXf
->maModel
.mnBorderId
: -1);
2324 if( const Border
* pBorder
= rStyles
.getBorder( nBorderId
).get() )
2326 if( (pAlignment
->getApiData().mnRotation
) && pBorder
->getApiData().hasAnyOuterBorder() )
2328 meRotationRef
= css::table::CellVertJustify2::BOTTOM
;
2329 eRotateMode
= SVX_ROTATE_MODE_BOTTOM
;
2332 ScfTools::PutItem( rItemSet
, SvxRotateModeItem( eRotateMode
, ATTR_ROTATE_MODE
), bSkipPoolDefs
);
2338 Dxf::Dxf( const WorkbookHelper
& rHelper
) :
2339 WorkbookHelper( rHelper
)
2343 FontRef
const & Dxf::createFont( bool bAlwaysNew
)
2345 if( bAlwaysNew
|| !mxFont
)
2346 mxFont
= std::make_shared
<Font
>( *this, true );
2350 BorderRef
const & Dxf::createBorder( bool bAlwaysNew
)
2352 if( bAlwaysNew
|| !mxBorder
)
2353 mxBorder
= std::make_shared
<Border
>( *this, true );
2357 FillRef
const & Dxf::createFill( bool bAlwaysNew
)
2359 if( bAlwaysNew
|| !mxFill
)
2360 mxFill
= std::make_shared
<Fill
>( *this, true );
2364 ProtectionRef
const & Dxf::createProtection( bool bAlwaysNew
)
2366 if ( bAlwaysNew
|| !mxProtection
)
2367 mxProtection
= std::make_shared
<Protection
>( *this, true );
2368 return mxProtection
;
2371 void Dxf::importNumFmt( const AttributeList
& rAttribs
)
2373 // don't propagate number formats defined in Dxf entries
2374 // they can have the same id ( but different format codes ) as those
2375 // defined globally earlier. We discard the id defined in XML_numFmtId
2376 // and generate one ourselves ( this assumes that the normal numberformat
2377 // import has already taken place )
2378 sal_Int32 nNumFmtId
= getStyles().nextFreeNumFmtId();
2379 OUString aFmtCode
= rAttribs
.getXString( XML_formatCode
, OUString() );
2380 mxNumFmt
= getStyles().createNumFmt( nNumFmtId
, aFmtCode
);
2383 void Dxf::importDxf( SequenceInputStream
& rStrm
)
2385 sal_Int32 nNumFmtId
= -1;
2387 sal_uInt16 nRecCount
;
2388 rStrm
.skip( 4 ); // flags
2389 nRecCount
= rStrm
.readuInt16();
2390 for( sal_uInt16 nRec
= 0; !rStrm
.isEof() && (nRec
< nRecCount
); ++nRec
)
2392 sal_uInt16 nSubRecId
, nSubRecSize
;
2393 sal_Int64 nRecEnd
= rStrm
.tell();
2394 nSubRecId
= rStrm
.readuInt16();
2395 nSubRecSize
= rStrm
.readuInt16();
2396 nRecEnd
+= nSubRecSize
;
2399 case BIFF12_DXF_FILL_PATTERN
: createFill( false )->importDxfPattern( rStrm
); break;
2400 case BIFF12_DXF_FILL_FGCOLOR
: createFill( false )->importDxfFgColor( rStrm
); break;
2401 case BIFF12_DXF_FILL_BGCOLOR
: createFill( false )->importDxfBgColor( rStrm
); break;
2402 case BIFF12_DXF_FILL_GRADIENT
: createFill( false )->importDxfGradient( rStrm
); break;
2403 case BIFF12_DXF_FILL_STOP
: createFill( false )->importDxfStop( rStrm
); break;
2404 case BIFF12_DXF_FONT_COLOR
: createFont( false )->importDxfColor( rStrm
); break;
2405 case BIFF12_DXF_BORDER_TOP
: createBorder( false )->importDxfBorder( XLS_TOKEN( top
), rStrm
); break;
2406 case BIFF12_DXF_BORDER_BOTTOM
: createBorder( false )->importDxfBorder( XLS_TOKEN( bottom
), rStrm
); break;
2407 case BIFF12_DXF_BORDER_LEFT
: createBorder( false )->importDxfBorder( XLS_TOKEN( left
), rStrm
); break;
2408 case BIFF12_DXF_BORDER_RIGHT
: createBorder( false )->importDxfBorder( XLS_TOKEN( right
), rStrm
); break;
2409 case BIFF12_DXF_FONT_NAME
: createFont( false )->importDxfName( rStrm
); break;
2410 case BIFF12_DXF_FONT_WEIGHT
: createFont( false )->importDxfWeight( rStrm
); break;
2411 case BIFF12_DXF_FONT_UNDERLINE
: createFont( false )->importDxfUnderline( rStrm
); break;
2412 case BIFF12_DXF_FONT_ESCAPEMENT
: createFont( false )->importDxfEscapement( rStrm
); break;
2413 case BIFF12_DXF_FONT_ITALIC
: createFont( false )->importDxfFlag( XML_i
, rStrm
); break;
2414 case BIFF12_DXF_FONT_STRIKE
: createFont( false )->importDxfFlag( XML_strike
, rStrm
); break;
2415 case BIFF12_DXF_FONT_OUTLINE
: createFont( false )->importDxfFlag( XML_outline
, rStrm
); break;
2416 case BIFF12_DXF_FONT_SHADOW
: createFont( false )->importDxfFlag( XML_shadow
, rStrm
); break;
2417 case BIFF12_DXF_FONT_HEIGHT
: createFont( false )->importDxfHeight( rStrm
); break;
2418 case BIFF12_DXF_FONT_SCHEME
: createFont( false )->importDxfScheme( rStrm
); break;
2419 case BIFF12_DXF_NUMFMT_CODE
: aFmtCode
= BiffHelper::readString( rStrm
, false ); break;
2420 case BIFF12_DXF_NUMFMT_ID
: nNumFmtId
= rStrm
.readuInt16(); break;
2421 case BIFF12_DXF_CELL_LOCKED
: createProtection( false )->importDxfProtection( XML_locked
, rStrm
); break;
2422 case BIFF12_DXF_CELL_HIDDEN
: createProtection( false )->importDxfProtection( XML_hidden
, rStrm
); break;
2424 rStrm
.seek( nRecEnd
);
2426 OSL_ENSURE( !rStrm
.isEof() && (rStrm
.getRemaining() == 0), "Dxf::importDxf - unexpected remaining data" );
2427 mxNumFmt
= getStyles().createNumFmt( nNumFmtId
, aFmtCode
);
2430 void Dxf::finalizeImport()
2433 mxFont
->finalizeImport();
2435 // number format already finalized by the number formats buffer
2438 mxAlignment
->finalizeImport();
2439 // how do we detect RTL when text dir is OOX_XF_CONTEXT? ( seems you
2440 // would need access to the cell content, which we don't here )
2441 if ( mxAlignment
->getModel().mnTextDir
== OOX_XF_TEXTDIR_RTL
)
2445 mxProtection
->finalizeImport();
2448 mxBorder
->finalizeImport( bRTL
);
2451 mxFill
->finalizeImport();
2454 void Dxf::fillToItemSet( SfxItemSet
& rSet
) const
2457 mxFont
->fillToItemSet(rSet
, false);
2459 mxNumFmt
->fillToItemSet(rSet
);
2461 mxAlignment
->fillToItemSet(rSet
);
2463 mxProtection
->fillToItemSet(rSet
);
2465 mxBorder
->fillToItemSet(rSet
);
2467 mxFill
->fillToItemSet(rSet
);
2472 const char* const sppcStyleNames
[] =
2475 "RowLevel_", // outline level will be appended
2476 "ColLevel_", // outline level will be appended
2480 "Comma [0]", // new in BIFF4
2482 "Hyperlink", // new in BIFF8
2483 "Followed Hyperlink",
2484 "Note", // new in OOX
2529 const sal_Int32 snStyleNamesCount
= static_cast< sal_Int32
>( SAL_N_ELEMENTS( sppcStyleNames
) );
2531 OUString
lclGetBuiltinStyleName( sal_Int32 nBuiltinId
, std::u16string_view rName
, sal_Int32 nLevel
= 0 )
2533 OSL_ENSURE( (0 <= nBuiltinId
) && (nBuiltinId
< snStyleNamesCount
), "lclGetBuiltinStyleName - unknown built-in style" );
2534 OUStringBuffer
aStyleName("Excel Built-in ");
2535 if( (0 <= nBuiltinId
) && (nBuiltinId
< snStyleNamesCount
) && (sppcStyleNames
[ nBuiltinId
] != nullptr) )
2536 aStyleName
.appendAscii( sppcStyleNames
[ nBuiltinId
] );
2537 else if( !rName
.empty() )
2538 aStyleName
.append( rName
);
2540 aStyleName
.append( nBuiltinId
);
2541 if( (nBuiltinId
== OOX_STYLE_ROWLEVEL
) || (nBuiltinId
== OOX_STYLE_COLLEVEL
) )
2542 aStyleName
.append( nLevel
);
2543 return aStyleName
.makeStringAndClear();
2546 OUString
lclCreateStyleName( const CellStyleModel
& rModel
)
2548 return rModel
.mbBuiltin
? lclGetBuiltinStyleName( rModel
.mnBuiltinId
, rModel
.maName
, rModel
.mnLevel
) : rModel
.maName
;
2553 CellStyleModel::CellStyleModel() :
2563 bool CellStyleModel::isBuiltin() const
2565 return mbBuiltin
&& (mnBuiltinId
>= 0);
2568 bool CellStyleModel::isDefaultStyle() const
2570 return mbBuiltin
&& (mnBuiltinId
== OOX_STYLE_NORMAL
);
2573 CellStyle::CellStyle( const WorkbookHelper
& rHelper
) :
2574 WorkbookHelper( rHelper
),
2576 mpStyleSheet( nullptr )
2580 void CellStyle::importCellStyle( const AttributeList
& rAttribs
)
2582 maModel
.maName
= rAttribs
.getXString( XML_name
, OUString() );
2583 maModel
.mnXfId
= rAttribs
.getInteger( XML_xfId
, -1 );
2584 maModel
.mnBuiltinId
= rAttribs
.getInteger( XML_builtinId
, -1 );
2585 maModel
.mnLevel
= rAttribs
.getInteger( XML_iLevel
, 0 );
2586 maModel
.mbBuiltin
= rAttribs
.hasAttribute( XML_builtinId
);
2587 maModel
.mbCustom
= rAttribs
.getBool( XML_customBuiltin
, false );
2588 maModel
.mbHidden
= rAttribs
.getBool( XML_hidden
, false );
2591 void CellStyle::importCellStyle( SequenceInputStream
& rStrm
)
2594 maModel
.mnXfId
= rStrm
.readInt32();
2595 nFlags
= rStrm
.readuInt16();
2596 maModel
.mnBuiltinId
= rStrm
.readInt8();
2597 maModel
.mnLevel
= rStrm
.readInt8();
2598 rStrm
>> maModel
.maName
;
2599 maModel
.mbBuiltin
= getFlag( nFlags
, BIFF12_CELLSTYLE_BUILTIN
);
2600 maModel
.mbCustom
= getFlag( nFlags
, BIFF12_CELLSTYLE_CUSTOM
);
2601 maModel
.mbHidden
= getFlag( nFlags
, BIFF12_CELLSTYLE_HIDDEN
);
2604 void CellStyle::createCellStyle()
2607 // #i1624# #i1768# ignore unnamed user styles
2608 bool bDefStyle
= maModel
.isDefaultStyle();
2611 if ( bDefStyle
&& maFinalName
.isEmpty() )
2612 maFinalName
= ScResId( STR_STYLENAME_STANDARD
);
2613 mbCreated
= maFinalName
.isEmpty();
2616 if( mbCreated
|| mpStyleSheet
)
2619 bool bCreatePattern
= false;
2620 Xf
* pXF
= getStyles().getStyleXf( maModel
.mnXfId
).get();
2621 ::ScDocument
& rDoc
= getScDocument();
2625 // use existing "Default" style sheet
2626 mpStyleSheet
= static_cast< ScStyleSheet
* >( rDoc
.GetStyleSheetPool()->Find(
2627 ScResId( STR_STYLENAME_STANDARD
), SfxStyleFamily::Para
) );
2628 OSL_ENSURE( mpStyleSheet
, "CellStyle::createStyle - Default style not found" );
2629 bCreatePattern
= true;
2633 mpStyleSheet
= static_cast< ScStyleSheet
* >( rDoc
.GetStyleSheetPool()->Find( maFinalName
, SfxStyleFamily::Para
) );
2636 mpStyleSheet
= &static_cast< ScStyleSheet
& >( rDoc
.GetStyleSheetPool()->Make( maFinalName
, SfxStyleFamily::Para
, SfxStyleSearchBits::UserDefined
) );
2637 bCreatePattern
= true;
2641 // bDefStyle==true omits default pool items in CreatePattern()
2642 if( bCreatePattern
&& mpStyleSheet
&& pXF
)
2643 mpStyleSheet
->GetItemSet().Put( pXF
->createPattern( bDefStyle
).GetItemSet() );
2646 void CellStyle::finalizeImport( const OUString
& rFinalName
)
2648 maFinalName
= rFinalName
;
2649 if( !maModel
.isBuiltin() || maModel
.mbCustom
)
2653 CellStyleBuffer::CellStyleBuffer( const WorkbookHelper
& rHelper
) :
2654 WorkbookHelper( rHelper
)
2658 CellStyleRef
CellStyleBuffer::importCellStyle( const AttributeList
& rAttribs
)
2660 CellStyleRef xCellStyle
= std::make_shared
<CellStyle
>( *this );
2661 xCellStyle
->importCellStyle( rAttribs
);
2662 insertCellStyle( xCellStyle
);
2666 CellStyleRef
CellStyleBuffer::importCellStyle( SequenceInputStream
& rStrm
)
2668 CellStyleRef xCellStyle
= std::make_shared
<CellStyle
>( *this );
2669 xCellStyle
->importCellStyle( rStrm
);
2670 insertCellStyle( xCellStyle
);
2674 void CellStyleBuffer::finalizeImport()
2676 // calculate final names of all styles
2677 typedef RefMap
< OUString
, CellStyle
, IgnoreCaseCompare
> CellStyleNameMap
;
2678 CellStyleNameMap aCellStyles
;
2679 CellStyleVector aConflictNameStyles
;
2681 /* First, reserve style names that are built-in in Calc. This causes that
2682 imported cell styles get different unused names and thus do not try to
2683 overwrite these built-in styles. */
2686 // unfortunately, com.sun.star.style.StyleFamily does not implement XEnumerationAccess...
2687 Reference
< XIndexAccess
> xStyleFamilyIA( getCellStyleFamily(), UNO_QUERY_THROW
);
2688 for( sal_Int32 nIndex
= 0, nCount
= xStyleFamilyIA
->getCount(); nIndex
< nCount
; ++nIndex
)
2690 Reference
< XStyle
> xStyle( xStyleFamilyIA
->getByIndex( nIndex
), UNO_QUERY_THROW
);
2691 if( !xStyle
->isUserDefined() )
2693 // create an empty entry by using ::std::map<>::operator[]
2694 aCellStyles
[ xStyle
->getName() ];
2702 /* Calculate names of built-in styles. Store styles with reserved names
2703 in the aConflictNameStyles list. */
2704 for( const auto& rxStyle
: maBuiltinStyles
)
2706 const CellStyleModel
& rModel
= rxStyle
->getModel();
2707 if (rModel
.isDefaultStyle())
2710 OUString aStyleName
= lclCreateStyleName( rModel
);
2711 /* If a builtin style entry already exists,
2712 we just stick with the last definition and ignore
2713 the preceding ones. */
2714 aCellStyles
[ aStyleName
] = rxStyle
;
2717 /* Calculate names of user defined styles. Store styles with reserved
2718 names in the aConflictNameStyles list. */
2719 for( const auto& rxStyle
: maUserStyles
)
2721 const CellStyleModel
& rModel
= rxStyle
->getModel();
2722 OUString aStyleName
= lclCreateStyleName( rModel
);
2723 // #i1624# #i1768# ignore unnamed user styles
2724 if( aStyleName
.getLength() > 0 )
2726 if( aCellStyles
.find( aStyleName
) != aCellStyles
.end() )
2727 aConflictNameStyles
.push_back( rxStyle
);
2729 aCellStyles
[ aStyleName
] = rxStyle
;
2733 // find unused names for all styles with conflicting names
2734 // having the index counter outside the loop prevents performance problems with opening some pathological documents (tdf#62095)
2735 sal_Int32 nIndex
= 0;
2736 for( const auto& rxStyle
: aConflictNameStyles
)
2738 const CellStyleModel
& rModel
= rxStyle
->getModel();
2739 OUString aStyleName
= lclCreateStyleName( rModel
);
2740 OUString aUnusedName
;
2743 aUnusedName
= aStyleName
+ OUStringChar(' ') + OUString::number( ++nIndex
);
2745 while( !aCellStyles
.try_emplace( aUnusedName
, rxStyle
).second
);
2748 // set final names and create user-defined and modified built-in cell styles
2749 aCellStyles
.forEachMemWithKey( &CellStyle::finalizeImport
);
2752 sal_Int32
CellStyleBuffer::getDefaultXfId() const
2754 return mxDefStyle
? mxDefStyle
->getModel().mnXfId
: -1;
2757 OUString
CellStyleBuffer::getDefaultStyleName() const
2759 return createCellStyle( mxDefStyle
);
2762 OUString
CellStyleBuffer::createCellStyle( sal_Int32 nXfId
) const
2764 return createCellStyle( maStylesByXf
.get( nXfId
) );
2767 ::ScStyleSheet
* CellStyleBuffer::getCellStyleSheet( sal_Int32 nXfId
) const
2769 return getCellStyleSheet( maStylesByXf
.get( nXfId
) );
2772 // private --------------------------------------------------------------------
2774 void CellStyleBuffer::insertCellStyle( CellStyleRef
const & xCellStyle
)
2776 const CellStyleModel
& rModel
= xCellStyle
->getModel();
2777 if( rModel
.mnXfId
< 0 )
2780 // insert into the built-in map or user defined map
2781 (rModel
.isBuiltin() ? maBuiltinStyles
: maUserStyles
).push_back( xCellStyle
);
2783 // insert into the XF identifier map
2784 OSL_ENSURE( maStylesByXf
.count( rModel
.mnXfId
) == 0, "CellStyleBuffer::insertCellStyle - multiple styles with equal XF identifier" );
2785 maStylesByXf
[ rModel
.mnXfId
] = xCellStyle
;
2787 // remember default cell style
2788 if( rModel
.isDefaultStyle() )
2789 mxDefStyle
= xCellStyle
;
2792 ::ScStyleSheet
* CellStyleBuffer::getCellStyleSheet( const CellStyleRef
& rxCellStyle
)
2794 ::ScStyleSheet
* pStyleSheet
= nullptr;
2796 pStyleSheet
= rxCellStyle
->getStyleSheet();
2800 OUString
CellStyleBuffer::createCellStyle( const CellStyleRef
& rxCellStyle
)
2804 rxCellStyle
->createCellStyle();
2805 const OUString
& rStyleName
= rxCellStyle
->getFinalStyleName();
2806 if( !rStyleName
.isEmpty() )
2809 // on error: fallback to default style
2810 return lclGetBuiltinStyleName( OOX_STYLE_NORMAL
, u
"" );
2813 AutoFormatModel::AutoFormatModel() :
2814 mnAutoFormatId( 0 ),
2815 mbApplyNumFmt( false ),
2816 mbApplyFont( false ),
2817 mbApplyAlignment( false ),
2818 mbApplyBorder( false ),
2819 mbApplyFill( false ),
2820 mbApplyProtection( false )
2824 StylesBuffer::StylesBuffer( const WorkbookHelper
& rHelper
) :
2825 WorkbookHelper( rHelper
),
2826 maPalette( rHelper
),
2827 maNumFmts( rHelper
),
2828 maCellStyles( rHelper
)
2832 FontRef
StylesBuffer::createFont()
2834 FontRef xFont
= std::make_shared
<Font
>( *this, false );
2835 maFonts
.push_back( xFont
);
2839 NumberFormatRef
StylesBuffer::createNumFmt( sal_Int32 nNumFmtId
, std::u16string_view aFmtCode
)
2841 return maNumFmts
.createNumFmt( nNumFmtId
, aFmtCode
);
2844 sal_Int32
StylesBuffer::nextFreeNumFmtId()
2846 return maNumFmts
.nextFreeId();
2849 BorderRef
StylesBuffer::createBorder()
2851 BorderRef xBorder
= std::make_shared
<Border
>( *this, false );
2852 maBorders
.push_back( xBorder
);
2856 FillRef
StylesBuffer::createFill()
2858 FillRef xFill
= std::make_shared
<Fill
>( *this, false );
2859 maFills
.push_back( xFill
);
2863 XfRef
StylesBuffer::createCellXf()
2865 XfRef xXf
= std::make_shared
<Xf
>( *this );
2866 maCellXfs
.push_back( xXf
);
2870 XfRef
StylesBuffer::createStyleXf()
2872 XfRef xXf
= std::make_shared
<Xf
>( *this );
2873 maStyleXfs
.push_back( xXf
);
2877 DxfRef
StylesBuffer::createDxf()
2879 DxfRef xDxf
= std::make_shared
<Dxf
>( *this );
2880 maDxfs
.push_back( xDxf
);
2884 DxfRef
StylesBuffer::createExtDxf()
2886 DxfRef xDxf
= std::make_shared
<Dxf
>( *this );
2887 maExtDxfs
.push_back( xDxf
);
2891 void StylesBuffer::importPaletteColor( const AttributeList
& rAttribs
)
2893 maPalette
.importPaletteColor( rAttribs
);
2896 NumberFormatRef
StylesBuffer::importNumFmt( const AttributeList
& rAttribs
)
2898 return maNumFmts
.importNumFmt( rAttribs
);
2901 CellStyleRef
StylesBuffer::importCellStyle( const AttributeList
& rAttribs
)
2903 return maCellStyles
.importCellStyle( rAttribs
);
2906 void StylesBuffer::importPaletteColor( SequenceInputStream
& rStrm
)
2908 maPalette
.importPaletteColor( rStrm
);
2911 void StylesBuffer::importNumFmt( SequenceInputStream
& rStrm
)
2913 maNumFmts
.importNumFmt( rStrm
);
2916 void StylesBuffer::importCellStyle( SequenceInputStream
& rStrm
)
2918 maCellStyles
.importCellStyle( rStrm
);
2921 void StylesBuffer::finalizeImport()
2923 // fonts first, are needed to finalize unit converter and XFs below
2924 maFonts
.forEachMem( &Font::finalizeImport
);
2925 // finalize unit coefficients after default font is known
2926 getUnitConverter().finalizeImport();
2928 maNumFmts
.finalizeImport();
2929 // borders and fills
2930 // is there a document wide RTL setting that we
2931 // would/could need to pass to finalizeImport here ?
2932 maBorders
.forEachMem( &Border::finalizeImport
, false );
2933 maFills
.forEachMem( &Fill::finalizeImport
);
2934 // style XFs and cell XFs
2935 maStyleXfs
.forEachMem( &Xf::finalizeImport
);
2936 maCellXfs
.forEachMem( &Xf::finalizeImport
);
2937 // built-in and user defined cell styles
2938 maCellStyles
.finalizeImport();
2939 // differential formatting (for conditional formatting)
2940 maDxfs
.forEachMem( &Dxf::finalizeImport
);
2943 ::Color
StylesBuffer::getPaletteColor( sal_Int32 nPaletteIdx
) const
2945 return maPalette
.getColor( nPaletteIdx
);
2948 FontRef
StylesBuffer::getFont( sal_Int32 nFontId
) const
2950 return maFonts
.get( nFontId
);
2953 BorderRef
StylesBuffer::getBorder( sal_Int32 nBorderId
) const
2955 return maBorders
.get( nBorderId
);
2958 XfRef
StylesBuffer::getCellXf( sal_Int32 nXfId
) const
2960 return maCellXfs
.get( nXfId
);
2963 XfRef
StylesBuffer::getStyleXf( sal_Int32 nXfId
) const
2965 return maStyleXfs
.get( nXfId
);
2968 FontRef
StylesBuffer::getFontFromCellXf( sal_Int32 nXfId
) const
2971 if( const Xf
* pXf
= getCellXf( nXfId
).get() )
2972 xFont
= pXf
->getFont();
2976 FontRef
StylesBuffer::getDefaultFont() const
2979 if( const Xf
* pXf
= getStyleXf( maCellStyles
.getDefaultXfId() ).get() )
2980 xDefFont
= pXf
->getFont();
2981 // no font from styles - try first loaded font (e.g. BIFF2)
2983 xDefFont
= maFonts
.get( 0 );
2984 OSL_ENSURE( xDefFont
, "StylesBuffer::getDefaultFont - no default font found" );
2988 const FontModel
& StylesBuffer::getDefaultFontModel() const
2990 FontRef xDefFont
= getDefaultFont();
2991 return xDefFont
? xDefFont
->getModel() : getTheme().getDefaultFontModel();
2994 bool StylesBuffer::equalBorders( sal_Int32 nBorderId1
, sal_Int32 nBorderId2
)
2996 // in OOXML, borders are assumed to be unique
2997 return nBorderId1
== nBorderId2
;
3000 bool StylesBuffer::equalFills( sal_Int32 nFillId1
, sal_Int32 nFillId2
)
3002 // in OOXML, fills are assumed to be unique
3003 return nFillId1
== nFillId2
;
3006 OUString
StylesBuffer::getDefaultStyleName() const
3008 return maCellStyles
.getDefaultStyleName();
3011 OUString
StylesBuffer::createCellStyle( sal_Int32 nXfId
) const
3013 return maCellStyles
.createCellStyle( nXfId
);
3016 ::ScStyleSheet
* StylesBuffer::getCellStyleSheet( sal_Int32 nXfId
) const
3018 return maCellStyles
.getCellStyleSheet( nXfId
);
3021 OUString
StylesBuffer::createDxfStyle( sal_Int32 nDxfId
) const
3023 OUString
& rStyleName
= maDxfStyles
[ nDxfId
];
3024 if (!rStyleName
.isEmpty())
3027 if (Dxf
* pDxf
= maDxfs
.get(nDxfId
).get())
3029 // FIXME: How can we know whether this dxf is for conditional formatting,
3030 // not for color filter? Currently this style is created for each dxf
3031 // (which might only be used by color filter)
3032 rStyleName
= "ConditionalStyle_" + OUString::number(nDxfId
+ 1);
3034 // Create a cell style. This may overwrite an existing style if
3035 // one with the same name exists.
3036 ScStyleSheet
& rStyleSheet
= ScfTools::MakeCellStyleSheet(
3037 *getScDocument().GetStyleSheetPool(), rStyleName
, true);
3039 rStyleSheet
.ResetParent();
3040 SfxItemSet
& rStyleItemSet
=
3041 rStyleSheet
.GetItemSet();
3043 pDxf
->fillToItemSet(rStyleItemSet
);
3047 // on error: fallback to default style
3048 if (rStyleName
.isEmpty())
3049 rStyleName
= maCellStyles
.getDefaultStyleName();
3054 OUString
StylesBuffer::createExtDxfStyle( sal_Int32 nDxfId
) const
3056 OUString rStyleName
;
3058 if (Dxf
* pDxf
= maExtDxfs
.get(nDxfId
).get())
3060 rStyleName
= "ExtConditionalStyle_" + OUString::number(nDxfId
+ 1);
3062 // Create a cell style. This may overwrite an existing style if
3063 // one with the same name exists.
3064 ScStyleSheet
& rStyleSheet
= ScfTools::MakeCellStyleSheet(
3065 *getScDocument().GetStyleSheetPool(), rStyleName
, true);
3067 rStyleSheet
.ResetParent();
3068 SfxItemSet
& rStyleItemSet
=
3069 rStyleSheet
.GetItemSet();
3071 pDxf
->fillToItemSet(rStyleItemSet
);
3074 // on error: fallback to default style
3075 if (rStyleName
.isEmpty())
3076 rStyleName
= maCellStyles
.getDefaultStyleName();
3081 DxfRef
StylesBuffer::getDxf(sal_Int32 nDxfId
) const
3083 return maDxfs
.get(nDxfId
);
3086 void StylesBuffer::writeFontToItemSet( SfxItemSet
& rItemSet
, sal_Int32 nFontId
, bool bSkipPoolDefs
) const
3088 if( Font
* pFont
= maFonts
.get( nFontId
).get() )
3089 pFont
->fillToItemSet( rItemSet
, false, bSkipPoolDefs
);
3092 sal_uInt32
StylesBuffer::writeNumFmtToItemSet( SfxItemSet
& rItemSet
, sal_uInt32 nNumFmtId
, bool bSkipPoolDefs
) const
3094 return maNumFmts
.fillToItemSet( rItemSet
, nNumFmtId
, bSkipPoolDefs
);
3097 void StylesBuffer::writeBorderToItemSet( SfxItemSet
& rItemSet
, sal_Int32 nBorderId
, bool bSkipPoolDefs
) const
3099 if( Border
* pBorder
= maBorders
.get( nBorderId
).get() )
3100 pBorder
->fillToItemSet( rItemSet
, bSkipPoolDefs
);
3103 void StylesBuffer::writeFillToItemSet( SfxItemSet
& rItemSet
, sal_Int32 nFillId
, bool bSkipPoolDefs
) const
3105 if( Fill
* pFill
= maFills
.get( nFillId
).get() )
3106 pFill
->fillToItemSet( rItemSet
, bSkipPoolDefs
);
3109 bool operator==( const XfModel
& rXfModel1
, const XfModel
& rXfModel2
)
3111 return ( rXfModel1
.mbCellXf
== rXfModel2
.mbCellXf
&&
3112 rXfModel1
.mnStyleXfId
== rXfModel2
.mnStyleXfId
&&
3113 rXfModel1
.mbFontUsed
== rXfModel2
.mbFontUsed
&&
3114 rXfModel1
.mnFontId
== rXfModel2
.mnFontId
&&
3115 rXfModel1
.mbNumFmtUsed
== rXfModel2
.mbNumFmtUsed
&&
3116 rXfModel1
.mnNumFmtId
== rXfModel2
.mnNumFmtId
&&
3117 rXfModel1
.mbAlignUsed
== rXfModel2
.mbAlignUsed
&&
3118 rXfModel1
.mbBorderUsed
== rXfModel2
.mbBorderUsed
&&
3119 rXfModel1
.mnBorderId
== rXfModel2
.mnBorderId
&&
3120 rXfModel1
.mbAreaUsed
== rXfModel2
.mbAreaUsed
&&
3121 rXfModel1
.mnFillId
== rXfModel2
.mnFillId
&&
3122 rXfModel1
.mbProtUsed
== rXfModel2
.mbProtUsed
);
3125 bool operator==( const Xf
& rXf1
, const Xf
& rXf2
)
3127 if ( rXf1
.maModel
== rXf2
.maModel
)
3129 if ( rXf1
.maModel
.mbAlignUsed
)
3131 if ( !( rXf1
.maAlignment
.getApiData() == rXf2
.maAlignment
.getApiData() ) )
3134 if ( rXf1
.maModel
.mbProtUsed
)
3136 if ( !( rXf1
.maProtection
.getApiData() == rXf2
.maProtection
.getApiData() ) )
3144 void StylesBuffer::writeCellXfToDoc(
3145 ScDocumentImport
& rDoc
, const ScRange
& rRange
, sal_Int32 nXfId
) const
3147 Xf
* pXf
= maCellXfs
.get(nXfId
).get();
3151 pXf
->writeToDoc(rDoc
, rRange
);
3156 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */