1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
4 *
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8 *
9 * This file incorporates work covered by the following license notice:
10 *
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
18 */
19
20 #include <stylesbuffer.hxx>
21
22 #include <com/sun/star/awt/FontDescriptor.hpp>
23 #include <com/sun/star/awt/FontFamily.hpp>
24 #include <com/sun/star/awt/FontPitch.hpp>
25 #include <com/sun/star/awt/FontSlant.hpp>
26 #include <com/sun/star/awt/FontStrikeout.hpp>
27 #include <com/sun/star/awt/FontType.hpp>
28 #include <com/sun/star/awt/FontWeight.hpp>
29 #include <com/sun/star/awt/FontUnderline.hpp>
30 #include <com/sun/star/awt/XDevice.hpp>
31 #include <com/sun/star/awt/XFont2.hpp>
32 #include <com/sun/star/container/XIndexAccess.hpp>
33 #include <com/sun/star/sheet/XSpreadsheetDocument.hpp>
34 #include <com/sun/star/style/XStyle.hpp>
35 #include <com/sun/star/text/WritingMode2.hpp>
36 #include <com/sun/star/table/BorderLineStyle.hpp>
37 #include <com/sun/star/table/CellVertJustify2.hpp>
38 #include <com/sun/star/table/CellJustifyMethod.hpp>
39 #include <editeng/justifyitem.hxx>
40 #include <editeng/frmdiritem.hxx>
41 #include <editeng/fontitem.hxx>
42 #include <editeng/postitem.hxx>
43 #include <editeng/fhgtitem.hxx>
44 #include <editeng/wghtitem.hxx>
45 #include <editeng/udlnitem.hxx>
46 #include <editeng/colritem.hxx>
47 #include <editeng/crossedoutitem.hxx>
48 #include <editeng/contouritem.hxx>
49 #include <editeng/escapementitem.hxx>
50 #include <editeng/shdditem.hxx>
51 #include <editeng/eeitem.hxx>
52 #include <editeng/borderline.hxx>
53 #include <editeng/boxitem.hxx>
54 #include <editeng/lineitem.hxx>
55 #include <editeng/brushitem.hxx>
56 #include <svx/rotmodit.hxx>
57 #include <tools/fontenum.hxx>
58 #include <tools/UnitConversion.hxx>
59 #include <vcl/unohelp.hxx>
60 #include <rtl/tencinfo.h>
61 #include <rtl/ustrbuf.hxx>
62 #include <sal/log.hxx>
63 #include <osl/diagnose.h>
64 #include <oox/core/filterbase.hxx>
65 #include <oox/helper/attributelist.hxx>
66 #include <oox/helper/binaryinputstream.hxx>
67 #include <oox/helper/containerhelper.hxx>
68 #include <oox/helper/propertymap.hxx>
69 #include <oox/helper/propertyset.hxx>
70 #include <oox/token/namespaces.hxx>
71 #include <oox/token/properties.hxx>
72 #include <oox/token/tokens.hxx>
73 #include <themebuffer.hxx>
74 #include <unitconverter.hxx>
75 #include <document.hxx>
76 #include <stlpool.hxx>
77 #include <docpool.hxx>
78 #include <ftools.hxx>
79 #include <scitems.hxx>
80 #include <attrib.hxx>
81 #include <globstr.hrc>
82 #include <scresid.hxx>
83 #include <xlconst.hxx>
84 #include <documentimport.hxx>
85 #include <numformat.hxx>
86 #include <patattr.hxx>
87 #include <stlsheet.hxx>
88 #include <biffhelper.hxx>
89
90 namespace oox::xls {
91
92 using namespace ::com::sun::star::awt;
93 using namespace ::com::sun::star::container;
94 using namespace ::com::sun::star::style;
95 using namespace ::com::sun::star::table;
96 using namespace ::com::sun::star::text;
97 using namespace ::com::sun::star::uno;
98
99
100 namespace {
101
102 // OOXML constants ------------------------------------------------------------
103
104 // OOXML predefined color indexes (also used in BIFF3-BIFF8)
105 const sal_Int32 OOX_COLOR_USEROFFSET = 0; /// First user defined color in palette (OOXML/BIFF12).
106
107 // OOXML font family (also used in BIFF)
108 const sal_Int32 OOX_FONTFAMILY_NONE = 0;
109 const sal_Int32 OOX_FONTFAMILY_ROMAN = 1;
110 const sal_Int32 OOX_FONTFAMILY_SWISS = 2;
111 const sal_Int32 OOX_FONTFAMILY_MODERN = 3;
112 const sal_Int32 OOX_FONTFAMILY_SCRIPT = 4;
113 const sal_Int32 OOX_FONTFAMILY_DECORATIVE = 5;
114
115 // OOXML cell text direction (also used in BIFF)
116 const sal_Int32 OOX_XF_TEXTDIR_CONTEXT = 0;
117 const sal_Int32 OOX_XF_TEXTDIR_LTR = 1;
118 const sal_Int32 OOX_XF_TEXTDIR_RTL = 2;
119
120 // OOXML cell rotation (also used in BIFF)
121 const sal_Int32 OOX_XF_ROTATION_NONE = 0;
122 const sal_Int32 OOX_XF_ROTATION_STACKED = 255;
123
124 // OOXML cell indentation
125 const sal_Int32 OOX_XF_INDENT_NONE = 0;
126
127 // OOXML built-in cell styles (also used in BIFF)
128 const sal_Int32 OOX_STYLE_NORMAL = 0; /// Default cell style.
129 const sal_Int32 OOX_STYLE_ROWLEVEL = 1; /// RowLevel_x cell style.
130 const sal_Int32 OOX_STYLE_COLLEVEL = 2; /// ColLevel_x cell style.
131
132 // BIFF12 constants -----------------------------------------------------------
133
134 // BIFF12 color types
135 const sal_uInt8 BIFF12_COLOR_AUTO = 0;
136 const sal_uInt8 BIFF12_COLOR_INDEXED = 1;
137 const sal_uInt8 BIFF12_COLOR_RGB = 2;
138 const sal_uInt8 BIFF12_COLOR_THEME = 3;
139
140 // BIFF12 diagonal borders
141 const sal_uInt8 BIFF12_BORDER_DIAG_TLBR = 0x01; /// Top-left to bottom-right.
142 const sal_uInt8 BIFF12_BORDER_DIAG_BLTR = 0x02; /// Bottom-left to top-right.
143
144 // BIFF12 gradient fill
145 const sal_Int32 BIFF12_FILL_GRADIENT = 40;
146
147 // BIFF12 XF flags
148 const sal_uInt32 BIFF12_XF_WRAPTEXT = 0x00400000;
149 const sal_uInt32 BIFF12_XF_JUSTLASTLINE = 0x00800000;
150 const sal_uInt32 BIFF12_XF_SHRINK = 0x01000000;
151 const sal_uInt32 BIFF12_XF_LOCKED = 0x10000000;
152 const sal_uInt32 BIFF12_XF_HIDDEN = 0x20000000;
153
154 // BIFF12 XF attribute used flags
155 const sal_uInt16 BIFF12_XF_NUMFMT_USED = 0x0001;
156 const sal_uInt16 BIFF12_XF_FONT_USED = 0x0002;
157 const sal_uInt16 BIFF12_XF_ALIGN_USED = 0x0004;
158 const sal_uInt16 BIFF12_XF_BORDER_USED = 0x0008;
159 const sal_uInt16 BIFF12_XF_AREA_USED = 0x0010;
160 const sal_uInt16 BIFF12_XF_PROT_USED = 0x0020;
161
162 // BIFF12 DXF constants
163 const sal_uInt16 BIFF12_DXF_FILL_PATTERN = 0;
164 const sal_uInt16 BIFF12_DXF_FILL_FGCOLOR = 1;
165 const sal_uInt16 BIFF12_DXF_FILL_BGCOLOR = 2;
166 const sal_uInt16 BIFF12_DXF_FILL_GRADIENT = 3;
167 const sal_uInt16 BIFF12_DXF_FILL_STOP = 4;
168 const sal_uInt16 BIFF12_DXF_FONT_COLOR = 5;
169 const sal_uInt16 BIFF12_DXF_BORDER_TOP = 6;
170 const sal_uInt16 BIFF12_DXF_BORDER_BOTTOM = 7;
171 const sal_uInt16 BIFF12_DXF_BORDER_LEFT = 8;
172 const sal_uInt16 BIFF12_DXF_BORDER_RIGHT = 9;
173 const sal_uInt16 BIFF12_DXF_FONT_NAME = 24;
174 const sal_uInt16 BIFF12_DXF_FONT_WEIGHT = 25;
175 const sal_uInt16 BIFF12_DXF_FONT_UNDERLINE = 26;
176 const sal_uInt16 BIFF12_DXF_FONT_ESCAPEMENT = 27;
177 const sal_uInt16 BIFF12_DXF_FONT_ITALIC = 28;
178 const sal_uInt16 BIFF12_DXF_FONT_STRIKE = 29;
179 const sal_uInt16 BIFF12_DXF_FONT_OUTLINE = 30;
180 const sal_uInt16 BIFF12_DXF_FONT_SHADOW = 31;
181 const sal_uInt16 BIFF12_DXF_FONT_HEIGHT = 36;
182 const sal_uInt16 BIFF12_DXF_FONT_SCHEME = 37;
183 const sal_uInt16 BIFF12_DXF_NUMFMT_CODE = 38;
184 const sal_uInt16 BIFF12_DXF_NUMFMT_ID = 41;
185
186 // BIFF12 CELLSTYLE flags
187 const sal_uInt16 BIFF12_CELLSTYLE_BUILTIN = 0x0001;
188 const sal_uInt16 BIFF12_CELLSTYLE_HIDDEN = 0x0002;
189 const sal_uInt16 BIFF12_CELLSTYLE_CUSTOM = 0x0004;
190
191 // BIFF constants -------------------------------------------------------------
192
193 // BIFF font flags, also used in BIFF12
194 const sal_uInt16 BIFF_FONTFLAG_ITALIC = 0x0002;
195 const sal_uInt16 BIFF_FONTFLAG_STRIKEOUT = 0x0008;
196 const sal_uInt16 BIFF_FONTFLAG_OUTLINE = 0x0010;
197 const sal_uInt16 BIFF_FONTFLAG_SHADOW = 0x0020;
198
199 // BIFF font weight
200 const sal_uInt16 BIFF_FONTWEIGHT_BOLD = 450;
201
202 // BIFF font underline, also used in BIFF12
203 const sal_uInt8 BIFF_FONTUNDERL_NONE = 0;
204 const sal_uInt8 BIFF_FONTUNDERL_SINGLE = 1;
205 const sal_uInt8 BIFF_FONTUNDERL_DOUBLE = 2;
206 const sal_uInt8 BIFF_FONTUNDERL_SINGLE_ACC = 33;
207 const sal_uInt8 BIFF_FONTUNDERL_DOUBLE_ACC = 34;
208
lclReadRgbColor(BinaryInputStream & rStrm)209 ::Color lclReadRgbColor( BinaryInputStream& rStrm )
210 {
211 sal_uInt8 nR, nG, nB, nA;
212 nR = rStrm.readuChar();
213 nG = rStrm.readuChar();
214 nB = rStrm.readuChar();
215 nA = rStrm.readuChar();
216 sal_Int32 nValue = nA;
217 nValue <<= 8;
218 nValue |= nR;
219 nValue <<= 8;
220 nValue |= nG;
221 nValue <<= 8;
222 nValue |= nB;
223 return ::Color(ColorTransparency, nValue);
224 }
225
226 } // namespace
227
ExcelGraphicHelper(const WorkbookHelper & rHelper)228 ExcelGraphicHelper::ExcelGraphicHelper( const WorkbookHelper& rHelper ) :
229 GraphicHelper( rHelper.getBaseFilter().getComponentContext(), rHelper.getBaseFilter().getTargetFrame(), rHelper.getBaseFilter().getStorage() ),
230 WorkbookHelper( rHelper )
231 {
232 }
233
getSchemeColor(sal_Int32 nToken) const234 ::Color ExcelGraphicHelper::getSchemeColor( sal_Int32 nToken ) const
235 {
236 return getTheme().getColorByToken( nToken );
237 }
238
getPaletteColor(sal_Int32 nPaletteIdx) const239 ::Color ExcelGraphicHelper::getPaletteColor( sal_Int32 nPaletteIdx ) const
240 {
241 return getStyles().getPaletteColor( nPaletteIdx );
242 }
243
setAuto()244 void Color::setAuto()
245 {
246 clearTransformations();
247 setSchemeClr( XML_phClr );
248 }
249
setRgb(::Color nRgbValue,double fTint)250 void Color::setRgb( ::Color nRgbValue, double fTint )
251 {
252 clearTransformations();
253 setSrgbClr( sal_uInt32(nRgbValue) & 0xFFFFFF );
254 if( fTint != 0.0 ) addExcelTintTransformation( fTint );
255 }
256
setTheme(sal_Int32 nThemeIdx,double fTint)257 void Color::setTheme( sal_Int32 nThemeIdx, double fTint )
258 {
259 clearTransformations();
260 static const sal_Int32 spnColorTokens[] = {
261 XML_lt1, XML_dk1, XML_lt2, XML_dk2, XML_accent1, XML_accent2,
262 XML_accent3, XML_accent4, XML_accent5, XML_accent6, XML_hlink, XML_folHlink };
263 setSchemeClr( STATIC_ARRAY_SELECT( spnColorTokens, nThemeIdx, XML_TOKEN_INVALID ) );
264 if( fTint != 0.0 ) addExcelTintTransformation( fTint );
265 }
266
setIndexed(sal_Int32 nPaletteIdx,double fTint)267 void Color::setIndexed( sal_Int32 nPaletteIdx, double fTint )
268 {
269 clearTransformations();
270 setPaletteClr( nPaletteIdx );
271 if( fTint != 0.0 ) addExcelTintTransformation( fTint );
272 }
273
importColor(const AttributeList & rAttribs)274 void Color::importColor( const AttributeList& rAttribs )
275 {
276 // tdf#113271 The order of import color is very important in case of more than one color attributes was provided.
277 // This order (theme -> rgb -> indexed -> auto) is not documented and was gathered experimentally based on MS Excel 2013.
278 if( rAttribs.hasAttribute( XML_theme ) )
279 setTheme( rAttribs.getInteger( XML_theme, -1 ), rAttribs.getDouble( XML_tint, 0.0 ) );
280 else if( rAttribs.hasAttribute( XML_rgb ) )
281 setRgb( ::Color(ColorTransparency, rAttribs.getIntegerHex( XML_rgb, sal_Int32(API_RGB_TRANSPARENT) ) ), rAttribs.getDouble( XML_tint, 0.0 ) );
282 else if( rAttribs.hasAttribute( XML_indexed ) )
283 setIndexed( rAttribs.getInteger( XML_indexed, -1 ), rAttribs.getDouble( XML_tint, 0.0 ) );
284 else if( rAttribs.getBool( XML_auto, false ) )
285 setAuto();
286 else
287 {
288 OSL_FAIL( "Color::importColor - unknown color type" );
289 setAuto();
290 }
291 }
292
importColor(SequenceInputStream & rStrm)293 void Color::importColor( SequenceInputStream& rStrm )
294 {
295 sal_uInt8 nFlags, nIndex;
296 sal_Int16 nTint;
297 nFlags = rStrm.readuChar();
298 nIndex = rStrm.readuChar();
299 nTint = rStrm.readInt16();
300
301 // scale tint from signed 16-bit to double range -1.0 ... 1.0
302 double fTint = nTint;
303 if( nTint < 0 )
304 fTint /= -SAL_MIN_INT16;
305 else if( nTint > 0 )
306 fTint /= SAL_MAX_INT16;
307
308 switch( extractValue< sal_uInt8 >( nFlags, 1, 7 ) )
309 {
310 case BIFF12_COLOR_AUTO:
311 setAuto();
312 rStrm.skip( 4 );
313 break;
314 case BIFF12_COLOR_INDEXED:
315 setIndexed( nIndex, fTint );
316 rStrm.skip( 4 );
317 break;
318 case BIFF12_COLOR_RGB:
319 setRgb( lclReadRgbColor( rStrm ), fTint );
320 break;
321 case BIFF12_COLOR_THEME:
322 setTheme( nIndex, fTint );
323 rStrm.skip( 4 );
324 break;
325 default:
326 OSL_FAIL( "Color::importColor - unknown color type" );
327 setAuto();
328 rStrm.skip( 4 );
329 }
330 }
331
importColorId(SequenceInputStream & rStrm)332 void Color::importColorId( SequenceInputStream& rStrm )
333 {
334 setIndexed( rStrm.readInt32() );
335 }
336
operator >>(SequenceInputStream & rStrm,Color & orColor)337 SequenceInputStream& operator>>( SequenceInputStream& rStrm, Color& orColor )
338 {
339 orColor.importColor( rStrm );
340 return rStrm;
341 }
342
343 namespace {
344
345 /** Standard EGA colors, bright. */
346 #define PALETTE_EGA_COLORS_LIGHT \
347 ::Color(0x000000), ::Color(0xFFFFFF), ::Color(0xFF0000), ::Color(0x00FF00), ::Color(0x0000FF), ::Color(0xFFFF00), ::Color(0xFF00FF), ::Color(0x00FFFF)
348 /** Standard EGA colors), dark. */
349 #define PALETTE_EGA_COLORS_DARK \
350 ::Color(0x800000), ::Color(0x008000), ::Color(0x000080), ::Color(0x808000), ::Color(0x800080), ::Color(0x008080), ::Color(0xC0C0C0), ::Color(0x808080)
351
352 /** Default color table for BIFF8/BIFF12/OOXML. */
353 const ::Color spnDefColors8[] =
354 {
355 /* 0 */ PALETTE_EGA_COLORS_LIGHT,
356 /* 8 */ PALETTE_EGA_COLORS_LIGHT,
357 /* 16 */ PALETTE_EGA_COLORS_DARK,
358 /* 24 */ ::Color(0x9999FF), ::Color(0x993366), ::Color(0xFFFFCC), ::Color(0xCCFFFF), ::Color(0x660066), ::Color(0xFF8080), ::Color(0x0066CC), ::Color(0xCCCCFF),
359 /* 32 */ ::Color(0x000080), ::Color(0xFF00FF), ::Color(0xFFFF00), ::Color(0x00FFFF), ::Color(0x800080), ::Color(0x800000), ::Color(0x008080), ::Color(0x0000FF),
360 /* 40 */ ::Color(0x00CCFF), ::Color(0xCCFFFF), ::Color(0xCCFFCC), ::Color(0xFFFF99), ::Color(0x99CCFF), ::Color(0xFF99CC), ::Color(0xCC99FF), ::Color(0xFFCC99),
361 /* 48 */ ::Color(0x3366FF), ::Color(0x33CCCC), ::Color(0x99CC00), ::Color(0xFFCC00), ::Color(0xFF9900), ::Color(0xFF6600), ::Color(0x666699), ::Color(0x969696),
362 /* 56 */ ::Color(0x003366), ::Color(0x339966), ::Color(0x003300), ::Color(0x333300), ::Color(0x993300), ::Color(0x993366), ::Color(0x333399), ::Color(0x333333)
363 };
364
365 #undef PALETTE_EGA_COLORS_LIGHT
366 #undef PALETTE_EGA_COLORS_DARK
367
368 } // namespace
369
ColorPalette(const WorkbookHelper & rHelper)370 ColorPalette::ColorPalette( const WorkbookHelper& rHelper )
371 : WorkbookHelper(rHelper)
372 , mnAppendIndex(0)
373 {
374 // default colors
375 maColors.insert( maColors.begin(), spnDefColors8, spnDefColors8 + SAL_N_ELEMENTS(spnDefColors8) );
376 mnAppendIndex = OOX_COLOR_USEROFFSET;
377 }
378
importPaletteColor(const AttributeList & rAttribs)379 void ColorPalette::importPaletteColor( const AttributeList& rAttribs )
380 {
381 appendColor( ::Color(ColorTransparency, rAttribs.getIntegerHex( XML_rgb, sal_Int32(API_RGB_WHITE) ) ) );
382 }
383
importPaletteColor(SequenceInputStream & rStrm)384 void ColorPalette::importPaletteColor( SequenceInputStream& rStrm )
385 {
386 ::Color nRgb = lclReadRgbColor( rStrm );
387 appendColor( nRgb );
388 }
389
getColor(sal_Int32 nPaletteIdx) const390 ::Color ColorPalette::getColor( sal_Int32 nPaletteIdx ) const
391 {
392 ::Color nColor = API_RGB_TRANSPARENT;
393 if( const ::Color* pnPaletteColor = ContainerHelper::getVectorElement( maColors, nPaletteIdx ) )
394 {
395 nColor = *pnPaletteColor;
396 }
397 else switch( nPaletteIdx )
398 {
399 case OOX_COLOR_WINDOWTEXT3:
400 case OOX_COLOR_WINDOWTEXT:
401 case OOX_COLOR_CHWINDOWTEXT: nColor = getBaseFilter().getGraphicHelper().getSystemColor( XML_windowText ); break;
402 case OOX_COLOR_WINDOWBACK3:
403 case OOX_COLOR_WINDOWBACK:
404 case OOX_COLOR_CHWINDOWBACK: nColor = getBaseFilter().getGraphicHelper().getSystemColor( XML_window ); break;
405 case OOX_COLOR_BUTTONBACK: nColor = getBaseFilter().getGraphicHelper().getSystemColor( XML_btnFace ); break;
406 case OOX_COLOR_CHBORDERAUTO: nColor = API_RGB_BLACK; /* really always black? */ break;
407 case OOX_COLOR_NOTEBACK: nColor = getBaseFilter().getGraphicHelper().getSystemColor( XML_infoBk ); break;
408 case OOX_COLOR_NOTETEXT: nColor = getBaseFilter().getGraphicHelper().getSystemColor( XML_infoText ); break;
409 case OOX_COLOR_FONTAUTO: nColor = API_RGB_TRANSPARENT; break;
410 default: OSL_FAIL( "ColorPalette::getColor - unknown color index" );
411 }
412 return nColor;
413 }
414
appendColor(::Color nRGBValue)415 void ColorPalette::appendColor( ::Color nRGBValue )
416 {
417 if( mnAppendIndex < maColors.size() )
418 maColors[ mnAppendIndex ] = nRGBValue;
419 else
420 maColors.push_back( nRGBValue );
421 ++mnAppendIndex;
422 }
423
424 namespace {
425
lclSetFontName(ApiScriptFontName & rFontName,const FontDescriptor & rFontDesc,bool bHasGlyphs)426 void lclSetFontName( ApiScriptFontName& rFontName, const FontDescriptor& rFontDesc, bool bHasGlyphs )
427 {
428 if( bHasGlyphs )
429 {
430 rFontName.maName = rFontDesc.Name;
431 rFontName.mnFamily = rFontDesc.Family;
432 // API font descriptor contains rtl_TextEncoding constants
433 rFontName.mnTextEnc = rFontDesc.CharSet;
434 }
435 else
436 {
437 rFontName = ApiScriptFontName();
438 }
439 }
440
441 } // namespace
442
FontModel()443 FontModel::FontModel() :
444 mnScheme( XML_none ),
445 mnFamily( OOX_FONTFAMILY_NONE ),
446 mnCharSet( WINDOWS_CHARSET_DEFAULT ),
447 mfHeight( 0.0 ),
448 mnUnderline( XML_none ),
449 mnEscapement( XML_baseline ),
450 mbBold( false ),
451 mbItalic( false ),
452 mbStrikeout( false ),
453 mbOutline( false ),
454 mbShadow( false )
455 {
456 }
457
setBiff12Scheme(sal_uInt8 nScheme)458 void FontModel::setBiff12Scheme( sal_uInt8 nScheme )
459 {
460 static const sal_Int32 spnSchemes[] = { XML_none, XML_major, XML_minor };
461 mnScheme = STATIC_ARRAY_SELECT( spnSchemes, nScheme, XML_none );
462 }
463
setBiffHeight(sal_uInt16 nHeight)464 void FontModel::setBiffHeight( sal_uInt16 nHeight )
465 {
466 mfHeight = nHeight / 20.0; // convert twips to points
467 }
468
setBiffWeight(sal_uInt16 nWeight)469 void FontModel::setBiffWeight( sal_uInt16 nWeight )
470 {
471 mbBold = nWeight >= BIFF_FONTWEIGHT_BOLD;
472 }
473
setBiffUnderline(sal_uInt16 nUnderline)474 void FontModel::setBiffUnderline( sal_uInt16 nUnderline )
475 {
476 switch( nUnderline )
477 {
478 case BIFF_FONTUNDERL_NONE: mnUnderline = XML_none; break;
479 case BIFF_FONTUNDERL_SINGLE: mnUnderline = XML_single; break;
480 case BIFF_FONTUNDERL_DOUBLE: mnUnderline = XML_double; break;
481 case BIFF_FONTUNDERL_SINGLE_ACC: mnUnderline = XML_singleAccounting; break;
482 case BIFF_FONTUNDERL_DOUBLE_ACC: mnUnderline = XML_doubleAccounting; break;
483 default: mnUnderline = XML_none;
484 }
485 }
486
setBiffEscapement(sal_uInt16 nEscapement)487 void FontModel::setBiffEscapement( sal_uInt16 nEscapement )
488 {
489 static const sal_Int32 spnEscapes[] = { XML_baseline, XML_superscript, XML_subscript };
490 mnEscapement = STATIC_ARRAY_SELECT( spnEscapes, nEscapement, XML_baseline );
491 }
492
ApiFontUsedFlags(bool bAllUsed)493 ApiFontUsedFlags::ApiFontUsedFlags( bool bAllUsed ) :
494 mbNameUsed( bAllUsed ),
495 mbColorUsed( bAllUsed ),
496 mbSchemeUsed( bAllUsed ),
497 mbHeightUsed( bAllUsed ),
498 mbUnderlineUsed( bAllUsed ),
499 mbEscapementUsed( bAllUsed ),
500 mbWeightUsed( bAllUsed ),
501 mbPostureUsed( bAllUsed ),
502 mbStrikeoutUsed( bAllUsed ),
503 mbOutlineUsed( bAllUsed ),
504 mbShadowUsed( bAllUsed )
505 {
506 }
507
ApiScriptFontName()508 ApiScriptFontName::ApiScriptFontName() :
509 mnFamily( css::awt::FontFamily::DONTKNOW ),
510 mnTextEnc( RTL_TEXTENCODING_DONTKNOW )
511 {
512 }
513
ApiFontData()514 ApiFontData::ApiFontData() :
515 maDesc(
516 "Calibri",
517 220, // height 11 points
518 0,
519 OUString(),
520 css::awt::FontFamily::DONTKNOW,
521 RTL_TEXTENCODING_DONTKNOW,
522 css::awt::FontPitch::DONTKNOW,
523 100.0,
524 css::awt::FontWeight::NORMAL,
525 css::awt::FontSlant_NONE,
526 css::awt::FontUnderline::NONE,
527 css::awt::FontStrikeout::NONE,
528 0.0,
529 false,
530 false,
531 css::awt::FontType::DONTKNOW ),
532 mnColor( API_RGB_TRANSPARENT ),
533 mnEscapement( API_ESCAPE_NONE ),
534 mnEscapeHeight( API_ESCAPEHEIGHT_NONE ),
535 mbOutline( false ),
536 mbShadow( false )
537 {
538 maLatinFont.maName = maDesc.Name;
539 }
540
Font(const WorkbookHelper & rHelper,bool bDxf)541 Font::Font( const WorkbookHelper& rHelper, bool bDxf ) :
542 WorkbookHelper( rHelper ),
543 maModel( rHelper.getTheme().getDefaultFontModel() ),
544 maUsedFlags( !bDxf ),
545 mbDxf( bDxf )
546 {
547 }
548
Font(const WorkbookHelper & rHelper,const FontModel & rModel)549 Font::Font( const WorkbookHelper& rHelper, const FontModel& rModel ) :
550 WorkbookHelper( rHelper ),
551 maModel( rModel ),
552 maUsedFlags( true ),
553 mbDxf( false )
554 {
555 }
556
importAttribs(sal_Int32 nElement,const AttributeList & rAttribs)557 void Font::importAttribs( sal_Int32 nElement, const AttributeList& rAttribs )
558 {
559 const FontModel& rDefModel = getTheme().getDefaultFontModel();
560 switch( nElement )
561 {
562 case XLS_TOKEN( name ): // when in <font> element
563 case XLS_TOKEN( rFont ): // when in <rPr> element
564 if( rAttribs.hasAttribute( XML_val ) )
565 {
566 maModel.maName = rAttribs.getXString( XML_val, OUString() );
567 maUsedFlags.mbNameUsed = true;
568 }
569 break;
570 case XLS_TOKEN( scheme ):
571 maModel.mnScheme = rAttribs.getToken( XML_val, rDefModel.mnScheme );
572 break;
573 case XLS_TOKEN( family ):
574 maModel.mnFamily = rAttribs.getInteger( XML_val, rDefModel.mnFamily );
575 break;
576 case XLS_TOKEN( charset ):
577 maModel.mnCharSet = rAttribs.getInteger( XML_val, rDefModel.mnCharSet );
578 break;
579 case XLS_TOKEN( sz ):
580 maModel.mfHeight = rAttribs.getDouble( XML_val, rDefModel.mfHeight );
581 maUsedFlags.mbHeightUsed = true;
582 break;
583 case XLS_TOKEN( color ):
584 maModel.maColor.importColor( rAttribs );
585 maUsedFlags.mbColorUsed = true;
586 break;
587 case XLS_TOKEN( u ):
588 maModel.mnUnderline = rAttribs.getToken( XML_val, XML_single );
589 maUsedFlags.mbUnderlineUsed = true;
590 break;
591 case XLS_TOKEN( vertAlign ):
592 maModel.mnEscapement = rAttribs.getToken( XML_val, XML_baseline );
593 maUsedFlags.mbEscapementUsed = true;
594 break;
595 case XLS_TOKEN( b ):
596 maModel.mbBold = rAttribs.getBool( XML_val, true );
597 maUsedFlags.mbWeightUsed = true;
598 break;
599 case XLS_TOKEN( i ):
600 maModel.mbItalic = rAttribs.getBool( XML_val, true );
601 maUsedFlags.mbPostureUsed = true;
602 break;
603 case XLS_TOKEN( strike ):
604 maModel.mbStrikeout = rAttribs.getBool( XML_val, true );
605 maUsedFlags.mbStrikeoutUsed = true;
606 break;
607 case XLS_TOKEN( outline ):
608 maModel.mbOutline = rAttribs.getBool( XML_val, true );
609 maUsedFlags.mbOutlineUsed = true;
610 break;
611 case XLS_TOKEN( shadow ):
612 maModel.mbShadow = rAttribs.getBool( XML_val, true );
613 maUsedFlags.mbShadowUsed = true;
614 break;
615 }
616 }
617
importFont(SequenceInputStream & rStrm)618 void Font::importFont( SequenceInputStream& rStrm )
619 {
620 SAL_WARN_IF( mbDxf, "sc", "Font::importFont - unexpected conditional formatting flag" );
621
622 sal_uInt16 nHeight, nFlags, nWeight, nEscapement;
623 sal_uInt8 nUnderline, nFamily, nCharSet, nScheme;
624 nHeight = rStrm.readuInt16();
625 nFlags = rStrm.readuInt16();
626 nWeight = rStrm.readuInt16();
627 nEscapement = rStrm.readuInt16();
628 nUnderline = rStrm.readuChar();
629 nFamily = rStrm.readuChar();
630 nCharSet = rStrm.readuChar();
631 rStrm.skip( 1 );
632 rStrm >> maModel.maColor;
633 nScheme = rStrm.readuChar();
634 rStrm >> maModel.maName;
635
636 // equal constants in all BIFFs for weight, underline, and escapement
637 maModel.setBiff12Scheme( nScheme );
638 maModel.setBiffHeight( nHeight );
639 maModel.setBiffWeight( nWeight );
640 maModel.setBiffUnderline( nUnderline );
641 maModel.setBiffEscapement( nEscapement );
642 maModel.mnFamily = nFamily;
643 maModel.mnCharSet = nCharSet;
644 // equal flags in all BIFFs
645 maModel.mbItalic = getFlag( nFlags, BIFF_FONTFLAG_ITALIC );
646 maModel.mbStrikeout = getFlag( nFlags, BIFF_FONTFLAG_STRIKEOUT );
647 maModel.mbOutline = getFlag( nFlags, BIFF_FONTFLAG_OUTLINE );
648 maModel.mbShadow = getFlag( nFlags, BIFF_FONTFLAG_SHADOW );
649 }
650
importDxfName(SequenceInputStream & rStrm)651 void Font::importDxfName( SequenceInputStream& rStrm )
652 {
653 SAL_WARN_IF( !mbDxf, "sc", "Font::importDxfName - missing conditional formatting flag" );
654 maModel.maName = BiffHelper::readString( rStrm, false );
655 maUsedFlags.mbColorUsed = true;
656 }
657
importDxfColor(SequenceInputStream & rStrm)658 void Font::importDxfColor( SequenceInputStream& rStrm )
659 {
660 SAL_WARN_IF( !mbDxf, "sc", "Font::importDxfColor - missing conditional formatting flag" );
661 rStrm >> maModel.maColor;
662 maUsedFlags.mbColorUsed = true;
663 }
664
importDxfScheme(SequenceInputStream & rStrm)665 void Font::importDxfScheme( SequenceInputStream& rStrm )
666 {
667 SAL_WARN_IF( !mbDxf, "sc", "Font::importDxfScheme - missing conditional formatting flag" );
668 maModel.setBiff12Scheme( rStrm.readuInt8() );
669 maUsedFlags.mbSchemeUsed = true;
670 }
671
importDxfHeight(SequenceInputStream & rStrm)672 void Font::importDxfHeight( SequenceInputStream& rStrm )
673 {
674 SAL_WARN_IF( !mbDxf, "sc", "Font::importDxfHeight - missing conditional formatting flag" );
675 maModel.setBiffHeight( rStrm.readuInt16() );
676 maUsedFlags.mbHeightUsed = true;
677 }
678
importDxfWeight(SequenceInputStream & rStrm)679 void Font::importDxfWeight( SequenceInputStream& rStrm )
680 {
681 SAL_WARN_IF( !mbDxf, "sc", "Font::importDxfWeight - missing conditional formatting flag" );
682 maModel.setBiffWeight( rStrm.readuInt16() );
683 maUsedFlags.mbWeightUsed = true;
684 }
685
importDxfUnderline(SequenceInputStream & rStrm)686 void Font::importDxfUnderline( SequenceInputStream& rStrm )
687 {
688 SAL_WARN_IF( !mbDxf, "sc", "Font::importDxfUnderline - missing conditional formatting flag" );
689 maModel.setBiffUnderline( rStrm.readuInt16() );
690 maUsedFlags.mbUnderlineUsed = true;
691 }
692
importDxfEscapement(SequenceInputStream & rStrm)693 void Font::importDxfEscapement( SequenceInputStream& rStrm )
694 {
695 SAL_WARN_IF( !mbDxf, "sc", "Font::importDxfEscapement - missing conditional formatting flag" );
696 maModel.setBiffEscapement( rStrm.readuInt16() );
697 maUsedFlags.mbEscapementUsed = true;
698 }
699
importDxfFlag(sal_Int32 nElement,SequenceInputStream & rStrm)700 void Font::importDxfFlag( sal_Int32 nElement, SequenceInputStream& rStrm )
701 {
702 SAL_WARN_IF( !mbDxf, "sc", "Font::importDxfFlag - missing conditional formatting flag" );
703 bool bFlag = rStrm.readuInt8() != 0;
704 switch( nElement )
705 {
706 case XML_i:
707 maModel.mbItalic = bFlag;
708 maUsedFlags.mbPostureUsed = true;
709 break;
710 case XML_strike:
711 maModel.mbStrikeout = bFlag;
712 maUsedFlags.mbStrikeoutUsed = true;
713 break;
714 case XML_outline:
715 maModel.mbOutline = bFlag;
716 maUsedFlags.mbOutlineUsed = true;
717 break;
718 case XML_shadow:
719 maModel.mbShadow = bFlag;
720 maUsedFlags.mbShadowUsed = true;
721 break;
722 default:
723 OSL_FAIL( "Font::importDxfFlag - unexpected element identifier" );
724 }
725 }
726
finalizeImport()727 void Font::finalizeImport()
728 {
729 // font name
730 maApiData.maDesc.Name = maModel.maName;
731
732 // font family
733 switch( maModel.mnFamily )
734 {
735 case OOX_FONTFAMILY_NONE: maApiData.maDesc.Family = css::awt::FontFamily::DONTKNOW; break;
736 case OOX_FONTFAMILY_ROMAN: maApiData.maDesc.Family = css::awt::FontFamily::ROMAN; break;
737 case OOX_FONTFAMILY_SWISS: maApiData.maDesc.Family = css::awt::FontFamily::SWISS; break;
738 case OOX_FONTFAMILY_MODERN: maApiData.maDesc.Family = css::awt::FontFamily::MODERN; break;
739 case OOX_FONTFAMILY_SCRIPT: maApiData.maDesc.Family = css::awt::FontFamily::SCRIPT; break;
740 case OOX_FONTFAMILY_DECORATIVE: maApiData.maDesc.Family = css::awt::FontFamily::DECORATIVE; break;
741 }
742
743 // character set (API font descriptor uses rtl_TextEncoding in member CharSet!)
744 if( (0 <= maModel.mnCharSet) && (maModel.mnCharSet <= SAL_MAX_UINT8) )
745 maApiData.maDesc.CharSet = static_cast< sal_Int16 >(
746 rtl_getTextEncodingFromWindowsCharset( static_cast< sal_uInt8 >( maModel.mnCharSet ) ) );
747
748 // color, height, weight, slant, strikeout, outline, shadow
749 maApiData.mnColor = maModel.maColor.getColor( getBaseFilter().getGraphicHelper() );
750 maApiData.maDesc.Height = static_cast< sal_Int16 >( maModel.mfHeight * 20.0 );
751 maApiData.maDesc.Weight = maModel.mbBold ? css::awt::FontWeight::BOLD : css::awt::FontWeight::NORMAL;
752 maApiData.maDesc.Slant = maModel.mbItalic ? css::awt::FontSlant_ITALIC : css::awt::FontSlant_NONE;
753 maApiData.maDesc.Strikeout = maModel.mbStrikeout ? css::awt::FontStrikeout::SINGLE : css::awt::FontStrikeout::NONE;
754 maApiData.mbOutline = maModel.mbOutline;
755 maApiData.mbShadow = maModel.mbShadow;
756
757 // underline
758 switch( maModel.mnUnderline )
759 {
760 case XML_double: maApiData.maDesc.Underline = css::awt::FontUnderline::DOUBLE; break;
761 case XML_doubleAccounting: maApiData.maDesc.Underline = css::awt::FontUnderline::DOUBLE; break;
762 case XML_none: maApiData.maDesc.Underline = css::awt::FontUnderline::NONE; break;
763 case XML_single: maApiData.maDesc.Underline = css::awt::FontUnderline::SINGLE; break;
764 case XML_singleAccounting: maApiData.maDesc.Underline = css::awt::FontUnderline::SINGLE; break;
765 }
766
767 // escapement
768 switch( maModel.mnEscapement )
769 {
770 case XML_baseline:
771 maApiData.mnEscapement = API_ESCAPE_NONE;
772 maApiData.mnEscapeHeight = API_ESCAPEHEIGHT_NONE;
773 break;
774 case XML_superscript:
775 maApiData.mnEscapement = API_ESCAPE_SUPERSCRIPT;
776 maApiData.mnEscapeHeight = API_ESCAPEHEIGHT_DEFAULT;
777 break;
778 case XML_subscript:
779 maApiData.mnEscapement = API_ESCAPE_SUBSCRIPT;
780 maApiData.mnEscapeHeight = API_ESCAPEHEIGHT_DEFAULT;
781 break;
782 }
783
784 // supported script types
785 if( !maUsedFlags.mbNameUsed )
786 return;
787
788 PropertySet aDocProps( getDocument() );
789 Reference< XDevice > xDevice( aDocProps.getAnyProperty( PROP_ReferenceDevice ), UNO_QUERY );
790 if( !xDevice.is() )
791 return;
792
793 Reference< XFont2 > xFont( xDevice->getFont( maApiData.maDesc ), UNO_QUERY );
794 if( !xFont.is() )
795 return;
796
797 // #91658# CJK fonts
798 bool bHasAsian =
799 xFont->hasGlyphs( OUString( u'\x3041' ) ) || // 3040-309F: Hiragana
800 xFont->hasGlyphs( OUString( u'\x30A1' ) ) || // 30A0-30FF: Katakana
801 xFont->hasGlyphs( OUString( u'\x3111' ) ) || // 3100-312F: Bopomofo
802 xFont->hasGlyphs( OUString( u'\x3131' ) ) || // 3130-318F: Hangul Compatibility Jamo
803 xFont->hasGlyphs( OUString( u'\x3301' ) ) || // 3300-33FF: CJK Compatibility
804 xFont->hasGlyphs( OUString( u'\x3401' ) ) || // 3400-4DBF: CJK Unified Ideographs Extension A
805 xFont->hasGlyphs( OUString( u'\x4E01' ) ) || // 4E00-9FFF: CJK Unified Ideographs
806 xFont->hasGlyphs( OUString( u'\x7E01' ) ) || // 4E00-9FFF: CJK Unified Ideographs
807 xFont->hasGlyphs( OUString( u'\xA001' ) ) || // A001-A48F: Yi Syllables
808 xFont->hasGlyphs( OUString( u'\xAC01' ) ) || // AC00-D7AF: Hangul Syllables
809 xFont->hasGlyphs( OUString( u'\xCC01' ) ) || // AC00-D7AF: Hangul Syllables
810 xFont->hasGlyphs( OUString( u'\xF901' ) ) || // F900-FAFF: CJK Compatibility Ideographs
811 xFont->hasGlyphs( OUString( u'\xFF71' ) ); // FF00-FFEF: Halfwidth/Fullwidth Forms
812 // #113783# CTL fonts
813 bool bHasCmplx =
814 xFont->hasGlyphs( OUString( u'\x05D1' ) ) || // 0590-05FF: Hebrew
815 xFont->hasGlyphs( OUString( u'\x0631' ) ) || // 0600-06FF: Arabic
816 xFont->hasGlyphs( OUString( u'\x0721' ) ) || // 0700-074F: Syriac
817 xFont->hasGlyphs( OUString( u'\x0911' ) ) || // 0900-0DFF: Indic scripts
818 xFont->hasGlyphs( OUString( u'\x0E01' ) ) || // 0E00-0E7F: Thai
819 xFont->hasGlyphs( OUString( u'\xFB21' ) ) || // FB1D-FB4F: Hebrew Presentation Forms
820 xFont->hasGlyphs( OUString( u'\xFB51' ) ) || // FB50-FDFF: Arabic Presentation Forms-A
821 xFont->hasGlyphs( OUString( u'\xFE71' ) ); // FE70-FEFF: Arabic Presentation Forms-B
822 // Western fonts
823 bool bHasLatin =
824 (!bHasAsian && !bHasCmplx) ||
825 xFont->hasGlyphs( OUString( 'A' ) );
826
827 lclSetFontName( maApiData.maLatinFont, maApiData.maDesc, bHasLatin );
828 lclSetFontName( maApiData.maAsianFont, maApiData.maDesc, bHasAsian );
829 lclSetFontName( maApiData.maCmplxFont, maApiData.maDesc, bHasCmplx );
830 }
831
needsRichTextFormat() const832 bool Font::needsRichTextFormat() const
833 {
834 return maApiData.mnEscapement != API_ESCAPE_NONE;
835 }
836
lcl_getFontFamily(sal_Int32 nFamily)837 static ::FontFamily lcl_getFontFamily( sal_Int32 nFamily )
838 {
839 ::FontFamily eScFamily = FAMILY_DONTKNOW;
840 switch( nFamily )
841 {
842 case css::awt::FontFamily::DONTKNOW:
843 eScFamily = FAMILY_DONTKNOW;
844 break;
845 case css::awt::FontFamily::ROMAN:
846 eScFamily = FAMILY_ROMAN;
847 break;
848 case css::awt::FontFamily::SWISS:
849 eScFamily = FAMILY_SWISS;
850 break;
851 case css::awt::FontFamily::MODERN:
852 eScFamily = FAMILY_MODERN;
853 break;
854 case css::awt::FontFamily::SCRIPT:
855 eScFamily = FAMILY_SCRIPT;
856 break;
857 case css::awt::FontFamily::DECORATIVE:
858 eScFamily = FAMILY_DECORATIVE;
859 break;
860 }
861 return eScFamily;
862 }
863
fillToItemSet(SfxItemSet & rItemSet,bool bEditEngineText,bool bSkipPoolDefs) const864 void Font::fillToItemSet( SfxItemSet& rItemSet, bool bEditEngineText, bool bSkipPoolDefs ) const
865 {
866 if ( maUsedFlags.mbNameUsed )
867 {
868 if( !maApiData.maLatinFont.maName.isEmpty() )
869 {
870 rtl_TextEncoding eFontEnc = maApiData.maLatinFont.mnTextEnc;
871 // taken from binary importer
872 rtl_TextEncoding eTempTextEnc = (bEditEngineText && (eFontEnc == getTextEncoding())) ?
873 ScfTools::GetSystemTextEncoding() : eFontEnc;
874
875 SvxFontItem aFontItem( lcl_getFontFamily( maApiData.maLatinFont.mnFamily ), maApiData.maLatinFont.maName, OUString(),
876 PITCH_DONTKNOW, eTempTextEnc, ATTR_FONT );
877 ScfTools::PutItem( rItemSet, aFontItem, bEditEngineText ? static_cast<sal_uInt16>(EE_CHAR_FONTINFO) : ATTR_FONT, bSkipPoolDefs );
878 }
879 if( !maApiData.maAsianFont.maName.isEmpty() )
880 {
881 rtl_TextEncoding eFontEnc = maApiData.maAsianFont.mnTextEnc;
882 // taken from binary importer
883 rtl_TextEncoding eTempTextEnc = (bEditEngineText && (eFontEnc == getTextEncoding())) ?
884 ScfTools::GetSystemTextEncoding() : eFontEnc;
885 SvxFontItem aFontItem( lcl_getFontFamily( maApiData.maAsianFont.mnFamily ), maApiData.maAsianFont.maName, OUString(),
886 PITCH_DONTKNOW, eTempTextEnc, ATTR_FONT );
887 ScfTools::PutItem( rItemSet, aFontItem, bEditEngineText ? static_cast<sal_uInt16>(EE_CHAR_FONTINFO_CJK) : ATTR_CJK_FONT, bSkipPoolDefs );
888 }
889 if( !maApiData.maCmplxFont.maName.isEmpty() )
890 {
891 rtl_TextEncoding eFontEnc = maApiData.maCmplxFont.mnTextEnc;
892 // taken from binary importer
893 rtl_TextEncoding eTempTextEnc = (bEditEngineText && (eFontEnc == getTextEncoding())) ?
894 ScfTools::GetSystemTextEncoding() : eFontEnc;
895 SvxFontItem aFontItem( lcl_getFontFamily( maApiData.maCmplxFont.mnFamily ), maApiData.maCmplxFont.maName, OUString(),
896 PITCH_DONTKNOW, eTempTextEnc, ATTR_FONT );
897 ScfTools::PutItem( rItemSet, aFontItem, bEditEngineText ? static_cast<sal_uInt16>(EE_CHAR_FONTINFO_CTL) : ATTR_CTL_FONT, bSkipPoolDefs );
898 }
899 }
900 // font height
901 if( maUsedFlags.mbHeightUsed )
902 {
903 sal_Int32 nHeight = maApiData.maDesc.Height;
904 // do we use XclFontItemType::HeaderFooter ( or is it just relevant for the binary filter )
905 if( bEditEngineText/* && (eType != XclFontItemType::HeaderFooter) */) // do not convert header/footer height
906 nHeight = convertTwipToMm100(nHeight);
907 SvxFontHeightItem aHeightItem( nHeight, 100, ATTR_FONT_HEIGHT );
908 ScfTools::PutItem( rItemSet, aHeightItem, bEditEngineText ? static_cast<sal_uInt16>(EE_CHAR_FONTHEIGHT) : ATTR_FONT_HEIGHT, bSkipPoolDefs );
909 ScfTools::PutItem( rItemSet, aHeightItem, bEditEngineText ? static_cast<sal_uInt16>(EE_CHAR_FONTHEIGHT_CJK) : ATTR_CJK_FONT_HEIGHT, bSkipPoolDefs );
910 ScfTools::PutItem( rItemSet, aHeightItem, bEditEngineText ? static_cast<sal_uInt16>(EE_CHAR_FONTHEIGHT_CTL) : ATTR_CTL_FONT_HEIGHT, bSkipPoolDefs );
911 }
912 // font weight
913 if( maUsedFlags.mbWeightUsed )
914 {
915 ::FontWeight fWeight = vcl::unohelper::ConvertFontWeight( maApiData.maDesc.Weight );
916 SvxWeightItem aWeightItem( fWeight, ATTR_FONT_WEIGHT );
917 ScfTools::PutItem( rItemSet, aWeightItem, bEditEngineText ? static_cast<sal_uInt16>(EE_CHAR_WEIGHT) : ATTR_FONT_WEIGHT, bSkipPoolDefs );
918 ScfTools::PutItem( rItemSet, aWeightItem, bEditEngineText ? static_cast<sal_uInt16>(EE_CHAR_WEIGHT_CTL) : ATTR_CTL_FONT_WEIGHT, bSkipPoolDefs );
919 ScfTools::PutItem( rItemSet, aWeightItem, bEditEngineText ? static_cast<sal_uInt16>(EE_CHAR_WEIGHT_CJK) : ATTR_CJK_FONT_WEIGHT, bSkipPoolDefs );
920 }
921 // font posture
922 if( maUsedFlags.mbPostureUsed )
923 {
924 SvxPostureItem aPostItem( ( maApiData.maDesc.Slant == css::awt::FontSlant_ITALIC ) ? ITALIC_NORMAL : ITALIC_NONE, ATTR_FONT_POSTURE);
925 ScfTools::PutItem( rItemSet, aPostItem, bEditEngineText ? static_cast<sal_uInt16>(EE_CHAR_ITALIC) : ATTR_FONT_POSTURE, bSkipPoolDefs );
926 ScfTools::PutItem( rItemSet, aPostItem, bEditEngineText ? static_cast<sal_uInt16>(EE_CHAR_ITALIC_CJK) : ATTR_CJK_FONT_POSTURE, bSkipPoolDefs );
927 ScfTools::PutItem( rItemSet, aPostItem, bEditEngineText ? static_cast<sal_uInt16>(EE_CHAR_ITALIC_CTL) : ATTR_CTL_FONT_POSTURE, bSkipPoolDefs );
928 }
929 // character color
930 if( maUsedFlags.mbColorUsed )
931 {
932 ScfTools::PutItem( rItemSet,SvxColorItem( maApiData.mnColor, bEditEngineText ? static_cast<sal_uInt16>(EE_CHAR_COLOR) : ATTR_FONT_COLOR), bSkipPoolDefs );
933 }
934 // underline style
935 if( maUsedFlags.mbUnderlineUsed )
936 {
937 FontLineStyle eScUnderl;
938 if ( maApiData.maDesc.Underline == css::awt::FontUnderline::DOUBLE )
939 eScUnderl = LINESTYLE_DOUBLE;
940 else if ( maApiData.maDesc.Underline == css::awt::FontUnderline::SINGLE )
941 eScUnderl = LINESTYLE_SINGLE;
942 else
943 eScUnderl = LINESTYLE_NONE;
944 SvxUnderlineItem aUnderlItem( eScUnderl, ATTR_FONT_UNDERLINE );
945 ScfTools::PutItem( rItemSet, aUnderlItem, bEditEngineText ? static_cast<sal_uInt16>(EE_CHAR_UNDERLINE) : ATTR_FONT_UNDERLINE, bSkipPoolDefs );
946 }
947 // strike out style
948 if( maUsedFlags.mbStrikeoutUsed )
949 {
950 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 );
951 }
952
953 // outline style
954 if( maUsedFlags.mbOutlineUsed )
955 {
956 ScfTools::PutItem( rItemSet, SvxContourItem( maApiData.mbOutline, ATTR_FONT_CONTOUR ), bEditEngineText ? static_cast<sal_uInt16>(EE_CHAR_OUTLINE) : ATTR_FONT_CONTOUR, bSkipPoolDefs );
957 }
958
959 // shadow style
960 if( maUsedFlags.mbShadowUsed )
961 {
962 ScfTools::PutItem( rItemSet, SvxShadowedItem( maApiData.mbShadow, ATTR_FONT_SHADOWED ), bEditEngineText ? static_cast<sal_uInt16>(EE_CHAR_SHADOW) : ATTR_FONT_SHADOWED, bSkipPoolDefs );
963 }
964 if( !maUsedFlags.mbEscapementUsed )
965 return;
966
967 SvxEscapement eScEscapem = SvxEscapement::Off;
968 if ( maApiData.mnEscapement == API_ESCAPE_SUPERSCRIPT )
969 eScEscapem = SvxEscapement::Superscript;
970 else if ( maApiData.mnEscapement == API_ESCAPE_SUBSCRIPT )
971 eScEscapem = SvxEscapement::Subscript;
972 if( bEditEngineText )
973 {
974 // #TODO handle EscapementHeight
975 rItemSet.Put( SvxEscapementItem( eScEscapem, EE_CHAR_ESCAPEMENT ) );
976 }
977 }
978
writeToPropertyMap(PropertyMap & rPropMap) const979 void Font::writeToPropertyMap( PropertyMap& rPropMap ) const
980 {
981 // font name properties
982 if( maUsedFlags.mbNameUsed )
983 {
984 if( !maApiData.maLatinFont.maName.isEmpty() )
985 {
986 rPropMap.setProperty( PROP_CharFontName, maApiData.maLatinFont.maName);
987 rPropMap.setProperty( PROP_CharFontFamily, maApiData.maLatinFont.mnFamily);
988 rPropMap.setProperty( PROP_CharFontCharSet, maApiData.maLatinFont.mnTextEnc);
989 }
990 if( !maApiData.maAsianFont.maName.isEmpty() )
991 {
992 rPropMap.setProperty( PROP_CharFontNameAsian, maApiData.maAsianFont.maName);
993 rPropMap.setProperty( PROP_CharFontFamilyAsian, maApiData.maAsianFont.mnFamily);
994 rPropMap.setProperty( PROP_CharFontCharSetAsian, maApiData.maAsianFont.mnTextEnc);
995 }
996 if( !maApiData.maCmplxFont.maName.isEmpty() )
997 {
998 rPropMap.setProperty( PROP_CharFontNameComplex, maApiData.maCmplxFont.maName);
999 rPropMap.setProperty( PROP_CharFontFamilyComplex, maApiData.maCmplxFont.mnFamily);
1000 rPropMap.setProperty( PROP_CharFontCharSetComplex, maApiData.maCmplxFont.mnTextEnc);
1001 }
1002 }
1003 // font height
1004 if( maUsedFlags.mbHeightUsed )
1005 {
1006 float fHeight = static_cast< float >( maApiData.maDesc.Height / 20.0 ); // twips to points
1007 rPropMap.setProperty( PROP_CharHeight, fHeight);
1008 rPropMap.setProperty( PROP_CharHeightAsian, fHeight);
1009 rPropMap.setProperty( PROP_CharHeightComplex, fHeight);
1010 }
1011 // font weight
1012 if( maUsedFlags.mbWeightUsed )
1013 {
1014 float fWeight = maApiData.maDesc.Weight;
1015 rPropMap.setProperty( PROP_CharWeight, fWeight);
1016 rPropMap.setProperty( PROP_CharWeightAsian, fWeight);
1017 rPropMap.setProperty( PROP_CharWeightComplex, fWeight);
1018 }
1019 // font posture
1020 if( maUsedFlags.mbPostureUsed )
1021 {
1022 rPropMap.setProperty( PROP_CharPosture, maApiData.maDesc.Slant);
1023 rPropMap.setProperty( PROP_CharPostureAsian, maApiData.maDesc.Slant);
1024 rPropMap.setProperty( PROP_CharPostureComplex, maApiData.maDesc.Slant);
1025 }
1026 // character color
1027 if( maUsedFlags.mbColorUsed )
1028 rPropMap.setProperty( PROP_CharColor, maApiData.mnColor);
1029 // underline style
1030 if( maUsedFlags.mbUnderlineUsed )
1031 rPropMap.setProperty( PROP_CharUnderline, maApiData.maDesc.Underline);
1032 // strike out style
1033 if( maUsedFlags.mbStrikeoutUsed )
1034 rPropMap.setProperty( PROP_CharStrikeout, maApiData.maDesc.Strikeout);
1035 // outline style
1036 if( maUsedFlags.mbOutlineUsed )
1037 rPropMap.setProperty( PROP_CharContoured, maApiData.mbOutline);
1038 // shadow style
1039 if( maUsedFlags.mbShadowUsed )
1040 rPropMap.setProperty( PROP_CharShadowed, maApiData.mbShadow);
1041 // escapement
1042 if( maUsedFlags.mbEscapementUsed )
1043 {
1044 rPropMap.setProperty( PROP_CharEscapement, maApiData.mnEscapement);
1045 rPropMap.setProperty( PROP_CharEscapementHeight, maApiData.mnEscapeHeight);
1046 }
1047 }
1048
writeToPropertySet(PropertySet & rPropSet) const1049 void Font::writeToPropertySet( PropertySet& rPropSet ) const
1050 {
1051 PropertyMap aPropMap;
1052 writeToPropertyMap( aPropMap );
1053 rPropSet.setProperties( aPropMap );
1054 }
1055
AlignmentModel()1056 AlignmentModel::AlignmentModel() :
1057 mnHorAlign( XML_general ),
1058 mnVerAlign( XML_bottom ),
1059 mnTextDir( OOX_XF_TEXTDIR_CONTEXT ),
1060 mnRotation( OOX_XF_ROTATION_NONE ),
1061 mnIndent( OOX_XF_INDENT_NONE ),
1062 mbWrapText( false ),
1063 mbShrink( false ),
1064 mbJustLastLine( false )
1065 {
1066 }
1067
setBiffHorAlign(sal_uInt8 nHorAlign)1068 void AlignmentModel::setBiffHorAlign( sal_uInt8 nHorAlign )
1069 {
1070 static const sal_Int32 spnHorAligns[] = {
1071 XML_general, XML_left, XML_center, XML_right,
1072 XML_fill, XML_justify, XML_centerContinuous, XML_distributed };
1073 mnHorAlign = STATIC_ARRAY_SELECT( spnHorAligns, nHorAlign, XML_general );
1074 }
1075
setBiffVerAlign(sal_uInt8 nVerAlign)1076 void AlignmentModel::setBiffVerAlign( sal_uInt8 nVerAlign )
1077 {
1078 static const sal_Int32 spnVerAligns[] = {
1079 XML_top, XML_center, XML_bottom, XML_justify, XML_distributed };
1080 mnVerAlign = STATIC_ARRAY_SELECT( spnVerAligns, nVerAlign, XML_bottom );
1081 }
1082
ApiAlignmentData()1083 ApiAlignmentData::ApiAlignmentData() :
1084 meHorJustify( css::table::CellHoriJustify_STANDARD ),
1085 mnHorJustifyMethod( css::table::CellJustifyMethod::AUTO ),
1086 mnVerJustify( css::table::CellVertJustify2::STANDARD ),
1087 mnVerJustifyMethod( css::table::CellJustifyMethod::AUTO ),
1088 meOrientation( css::table::CellOrientation_STANDARD ),
1089 mnRotation( 0 ),
1090 mnWritingMode( css::text::WritingMode2::PAGE ),
1091 mnIndent( 0 ),
1092 mbWrapText( false ),
1093 mbShrink( false )
1094 {
1095 }
1096
operator ==(const ApiAlignmentData & rLeft,const ApiAlignmentData & rRight)1097 bool operator==( const ApiAlignmentData& rLeft, const ApiAlignmentData& rRight )
1098 {
1099 return
1100 (rLeft.meHorJustify == rRight.meHorJustify) &&
1101 (rLeft.mnHorJustifyMethod == rRight.mnHorJustifyMethod) &&
1102 (rLeft.mnVerJustify == rRight.mnVerJustify) &&
1103 (rLeft.mnVerJustifyMethod == rRight.mnVerJustifyMethod) &&
1104 (rLeft.meOrientation == rRight.meOrientation) &&
1105 (rLeft.mnRotation == rRight.mnRotation) &&
1106 (rLeft.mnWritingMode == rRight.mnWritingMode) &&
1107 (rLeft.mnIndent == rRight.mnIndent) &&
1108 (rLeft.mbWrapText == rRight.mbWrapText) &&
1109 (rLeft.mbShrink == rRight.mbShrink);
1110 }
1111
Alignment(const WorkbookHelper & rHelper)1112 Alignment::Alignment( const WorkbookHelper& rHelper ) :
1113 WorkbookHelper( rHelper )
1114 {
1115 }
1116
importAlignment(const AttributeList & rAttribs)1117 void Alignment::importAlignment( const AttributeList& rAttribs )
1118 {
1119 maModel.mnVerAlign = rAttribs.getToken( XML_vertical, XML_bottom );
1120 maModel.mnTextDir = rAttribs.getInteger( XML_readingOrder, OOX_XF_TEXTDIR_CONTEXT );
1121 maModel.mnRotation = rAttribs.getInteger( XML_textRotation, OOX_XF_ROTATION_NONE );
1122 sal_Int32 nDefaultHorAlign = XML_general;
1123 if (maModel.mnRotation != OOX_XF_ROTATION_NONE)
1124 {
1125 if (maModel.mnRotation < 90 || maModel.mnRotation == 180)
1126 {
1127 nDefaultHorAlign = XML_left;
1128 }
1129 else
1130 {
1131 nDefaultHorAlign = XML_right;
1132 }
1133 }
1134 maModel.mnHorAlign = rAttribs.getToken( XML_horizontal, nDefaultHorAlign );
1135 maModel.mnIndent = rAttribs.getInteger( XML_indent, OOX_XF_INDENT_NONE );
1136 maModel.mbWrapText = rAttribs.getBool( XML_wrapText, false );
1137 maModel.mbShrink = rAttribs.getBool( XML_shrinkToFit, false );
1138 maModel.mbJustLastLine = rAttribs.getBool( XML_justifyLastLine, false );
1139 }
1140
setBiff12Data(sal_uInt32 nFlags)1141 void Alignment::setBiff12Data( sal_uInt32 nFlags )
1142 {
1143 maModel.setBiffHorAlign( extractValue< sal_uInt8 >( nFlags, 16, 3 ) );
1144 maModel.setBiffVerAlign( extractValue< sal_uInt8 >( nFlags, 19, 3 ) );
1145 maModel.mnTextDir = extractValue< sal_Int32 >( nFlags, 26, 2 );
1146 maModel.mnRotation = extractValue< sal_Int32 >( nFlags, 0, 8 );
1147 maModel.mnIndent = extractValue< sal_uInt8 >( nFlags, 8, 8 );
1148 maModel.mbWrapText = getFlag( nFlags, BIFF12_XF_WRAPTEXT );
1149 maModel.mbShrink = getFlag( nFlags, BIFF12_XF_SHRINK );
1150 maModel.mbJustLastLine = getFlag( nFlags, BIFF12_XF_JUSTLASTLINE );
1151 }
1152
finalizeImport()1153 void Alignment::finalizeImport()
1154 {
1155 // horizontal alignment
1156 switch( maModel.mnHorAlign )
1157 {
1158 case XML_center: maApiData.meHorJustify = css::table::CellHoriJustify_CENTER; break;
1159 case XML_centerContinuous: maApiData.meHorJustify = css::table::CellHoriJustify_CENTER; break;
1160 case XML_distributed: maApiData.meHorJustify = css::table::CellHoriJustify_BLOCK; break;
1161 case XML_fill: maApiData.meHorJustify = css::table::CellHoriJustify_REPEAT; break;
1162 case XML_general: maApiData.meHorJustify = css::table::CellHoriJustify_STANDARD; break;
1163 case XML_justify: maApiData.meHorJustify = css::table::CellHoriJustify_BLOCK; break;
1164 case XML_left: maApiData.meHorJustify = css::table::CellHoriJustify_LEFT; break;
1165 case XML_right: maApiData.meHorJustify = css::table::CellHoriJustify_RIGHT; break;
1166 }
1167
1168 if (maModel.mnHorAlign == XML_distributed)
1169 maApiData.mnHorJustifyMethod = css::table::CellJustifyMethod::DISTRIBUTE;
1170
1171 // vertical alignment
1172 switch( maModel.mnVerAlign )
1173 {
1174 case XML_bottom: maApiData.mnVerJustify = css::table::CellVertJustify2::BOTTOM; break;
1175 case XML_center: maApiData.mnVerJustify = css::table::CellVertJustify2::CENTER; break;
1176 case XML_distributed: maApiData.mnVerJustify = css::table::CellVertJustify2::BLOCK; break;
1177 case XML_justify: maApiData.mnVerJustify = css::table::CellVertJustify2::BLOCK; break;
1178 case XML_top: maApiData.mnVerJustify = css::table::CellVertJustify2::TOP; break;
1179 }
1180
1181 if (maModel.mnVerAlign == XML_distributed)
1182 maApiData.mnVerJustifyMethod = css::table::CellJustifyMethod::DISTRIBUTE;
1183
1184 /* indentation: expressed as number of blocks of 3 space characters in
1185 OOXML. */
1186 UnitConverter& rUnitConverter = getUnitConverter();
1187 // Note: indents are stored in twips
1188 sal_Int32 nIndent = rUnitConverter.scaleValue( 3.0 * maModel.mnIndent, Unit::Space, Unit::Twip);
1189 if( (0 <= nIndent) && (nIndent <= SAL_MAX_INT16) )
1190 maApiData.mnIndent = static_cast< sal_Int16 >( nIndent );
1191
1192 // complex text direction
1193 switch( maModel.mnTextDir )
1194 {
1195 case OOX_XF_TEXTDIR_CONTEXT: maApiData.mnWritingMode = css::text::WritingMode2::PAGE; break;
1196 case OOX_XF_TEXTDIR_LTR: maApiData.mnWritingMode = css::text::WritingMode2::LR_TB; break;
1197 case OOX_XF_TEXTDIR_RTL: maApiData.mnWritingMode = css::text::WritingMode2::RL_TB; break;
1198 }
1199
1200 // rotation: 0-90 means 0 to 90 degrees ccw, 91-180 means 1 to 90 degrees cw, 255 means stacked
1201 sal_Int32 nOoxRot = maModel.mnRotation;
1202 maApiData.mnRotation = Degree100(((0 <= nOoxRot) && (nOoxRot <= 90)) ?
1203 (100 * nOoxRot) :
1204 (((91 <= nOoxRot) && (nOoxRot <= 180)) ? (100 * (450 - nOoxRot)) : 0));
1205
1206 // "Orientation" property used for character stacking
1207 maApiData.meOrientation = (nOoxRot == OOX_XF_ROTATION_STACKED) ?
1208 css::table::CellOrientation_STACKED : css::table::CellOrientation_STANDARD;
1209
1210 // alignment flags (#i84960 automatic line break, if vertically justified/distributed)
1211 maApiData.mbWrapText = maModel.mbWrapText || (maModel.mnVerAlign == XML_distributed) || (maModel.mnVerAlign == XML_justify);
1212 maApiData.mbShrink = maModel.mbShrink;
1213
1214 }
1215
GetScVerAlign() const1216 ::SvxCellVerJustify Alignment::GetScVerAlign() const
1217 {
1218 ::SvxCellVerJustify nVert = ::SvxCellVerJustify::Standard;
1219 switch ( maApiData.mnVerJustify )
1220 {
1221 case css::table::CellVertJustify2::BOTTOM:
1222 nVert = ::SvxCellVerJustify::Bottom;
1223 break;
1224 case css::table::CellVertJustify2::CENTER:
1225 nVert = ::SvxCellVerJustify::Center;
1226 break;
1227 case css::table::CellVertJustify2::TOP:
1228 nVert = ::SvxCellVerJustify::Top;
1229 break;
1230 case css::table::CellVertJustify2::BLOCK:
1231 nVert = ::SvxCellVerJustify::Block;
1232 break;
1233 case css::table::CellVertJustify2::STANDARD:
1234 default:
1235 nVert = ::SvxCellVerJustify::Standard;
1236 break;
1237 }
1238 return nVert;
1239 }
1240
GetScHorAlign() const1241 ::SvxCellHorJustify Alignment::GetScHorAlign() const
1242 {
1243 ::SvxCellHorJustify nHori = ::SvxCellHorJustify::Standard;
1244 switch( maApiData.meHorJustify )
1245 {
1246 case css::table::CellHoriJustify_LEFT:
1247 nHori = ::SvxCellHorJustify::Left;
1248 break;
1249 case css::table::CellHoriJustify_CENTER:
1250 nHori = ::SvxCellHorJustify::Center;
1251 break;
1252 case css::table::CellHoriJustify_RIGHT:
1253 nHori = ::SvxCellHorJustify::Right;
1254 break;
1255 case css::table::CellHoriJustify_BLOCK:
1256 nHori = ::SvxCellHorJustify::Block;
1257 break;
1258 case css::table::CellHoriJustify_REPEAT:
1259 nHori = ::SvxCellHorJustify::Repeat;
1260 break;
1261 case css::table::CellHoriJustify_STANDARD:
1262 default:
1263 nHori = ::SvxCellHorJustify::Standard;
1264 break;
1265 }
1266 return nHori;
1267 }
1268
GetScFrameDir() const1269 SvxFrameDirection Alignment::GetScFrameDir() const
1270 {
1271 SvxFrameDirection eFrameDir = SvxFrameDirection::Environment;
1272 switch( maApiData.mnWritingMode )
1273 {
1274 case css::text::WritingMode2::PAGE:
1275 eFrameDir = SvxFrameDirection::Environment;
1276 break;
1277 case css::text::WritingMode2::LR_TB:
1278 eFrameDir = SvxFrameDirection::Horizontal_LR_TB;
1279 break;
1280 case css::text::WritingMode2::RL_TB:
1281 eFrameDir = SvxFrameDirection::Horizontal_RL_TB;
1282 break;
1283 default:
1284 OSL_FAIL( "GetScFrameDir - unknown CTL text direction" );
1285 }
1286 return eFrameDir;
1287 }
1288
fillToItemSet(SfxItemSet & rItemSet,bool bSkipPoolDefs) const1289 void Alignment::fillToItemSet( SfxItemSet& rItemSet, bool bSkipPoolDefs ) const
1290 {
1291 // horizontal alignment
1292 ScfTools::PutItem( rItemSet, SvxHorJustifyItem( GetScHorAlign(), ATTR_HOR_JUSTIFY ), bSkipPoolDefs );
1293 ScfTools::PutItem( rItemSet, SvxJustifyMethodItem( ( maApiData.mnHorJustifyMethod == css::table::CellJustifyMethod::DISTRIBUTE ) ? ::SvxCellJustifyMethod::Distribute : ::SvxCellJustifyMethod::Auto, ATTR_HOR_JUSTIFY_METHOD ), bSkipPoolDefs );
1294 ScfTools::PutItem( rItemSet, SvxVerJustifyItem( GetScVerAlign(), ATTR_VER_JUSTIFY ), bSkipPoolDefs );
1295 // vertical alignment
1296 ScfTools::PutItem( rItemSet, SvxJustifyMethodItem( ( maApiData.mnVerJustifyMethod == css::table::CellJustifyMethod::DISTRIBUTE ) ? ::SvxCellJustifyMethod::Distribute : ::SvxCellJustifyMethod::Auto, ATTR_VER_JUSTIFY_METHOD ), bSkipPoolDefs );
1297
1298 // CTL text direction
1299 ScfTools::PutItem( rItemSet, SvxFrameDirectionItem( GetScFrameDir(), ATTR_WRITINGDIR ), bSkipPoolDefs );
1300 // set an angle in the range from -90 to 90 degrees
1301 ScfTools::PutItem( rItemSet, ScRotateValueItem( maApiData.mnRotation ), bSkipPoolDefs );
1302 // Orientation
1303 ScfTools::PutItem( rItemSet, ScVerticalStackCell( maApiData.meOrientation == css::table::CellOrientation_STACKED ), bSkipPoolDefs );
1304 // indent
1305 ScfTools::PutItem( rItemSet, ScIndentItem( maApiData.mnIndent ), bSkipPoolDefs );
1306 // line wrap
1307 ScfTools::PutItem( rItemSet, ScLineBreakCell( maApiData.mbWrapText ), bSkipPoolDefs );
1308 ScfTools::PutItem( rItemSet, ScShrinkToFitCell( maApiData.mbShrink ), bSkipPoolDefs );
1309 }
1310
ProtectionModel()1311 ProtectionModel::ProtectionModel() :
1312 mbLocked( true ), // default in Excel and Calc
1313 mbHidden( false )
1314 {
1315 }
1316
ApiProtectionData()1317 ApiProtectionData::ApiProtectionData() :
1318 maCellProt( true, false, false, false )
1319 {
1320 }
1321
operator ==(const ApiProtectionData & rLeft,const ApiProtectionData & rRight)1322 bool operator==( const ApiProtectionData& rLeft, const ApiProtectionData& rRight )
1323 {
1324 return
1325 (rLeft.maCellProt.IsLocked == rRight.maCellProt.IsLocked) &&
1326 (rLeft.maCellProt.IsFormulaHidden == rRight.maCellProt.IsFormulaHidden) &&
1327 (rLeft.maCellProt.IsHidden == rRight.maCellProt.IsHidden) &&
1328 (rLeft.maCellProt.IsPrintHidden == rRight.maCellProt.IsPrintHidden);
1329 }
1330
Protection(const WorkbookHelper & rHelper)1331 Protection::Protection( const WorkbookHelper& rHelper ) :
1332 WorkbookHelper( rHelper )
1333 {
1334 }
1335
importProtection(const AttributeList & rAttribs)1336 void Protection::importProtection( const AttributeList& rAttribs )
1337 {
1338 maModel.mbLocked = rAttribs.getBool( XML_locked, true );
1339 maModel.mbHidden = rAttribs.getBool( XML_hidden, false );
1340 }
1341
setBiff12Data(sal_uInt32 nFlags)1342 void Protection::setBiff12Data( sal_uInt32 nFlags )
1343 {
1344 maModel.mbLocked = getFlag( nFlags, BIFF12_XF_LOCKED );
1345 maModel.mbHidden = getFlag( nFlags, BIFF12_XF_HIDDEN );
1346 }
1347
finalizeImport()1348 void Protection::finalizeImport()
1349 {
1350 maApiData.maCellProt.IsLocked = maModel.mbLocked;
1351 maApiData.maCellProt.IsFormulaHidden = maModel.mbHidden;
1352 }
1353
fillToItemSet(SfxItemSet & rItemSet,bool bSkipPoolDefs) const1354 void Protection::fillToItemSet( SfxItemSet& rItemSet, bool bSkipPoolDefs ) const
1355 {
1356 ScfTools::PutItem( rItemSet, ScProtectionAttr( maApiData.maCellProt.IsLocked, maApiData.maCellProt.IsFormulaHidden ), bSkipPoolDefs );
1357 }
1358
1359 namespace {
1360
lcl_isBorder(const css::table::BorderLine & rBorder)1361 bool lcl_isBorder(const css::table::BorderLine& rBorder)
1362 {
1363 return (rBorder.InnerLineWidth > 0) || (rBorder.OuterLineWidth > 0);
1364 }
1365
1366 }
1367
BorderLineModel(bool bDxf)1368 BorderLineModel::BorderLineModel( bool bDxf ) :
1369 mnStyle( XML_none ),
1370 mbUsed( !bDxf )
1371 {
1372 maColor.setIndexed( OOX_COLOR_WINDOWTEXT );
1373 }
1374
setBiffStyle(sal_Int32 nLineStyle)1375 void BorderLineModel::setBiffStyle( sal_Int32 nLineStyle )
1376 {
1377 static const sal_Int32 spnStyleIds[] = {
1378 XML_none, XML_thin, XML_medium, XML_dashed,
1379 XML_dotted, XML_thick, XML_double, XML_hair,
1380 XML_mediumDashed, XML_dashDot, XML_mediumDashDot, XML_dashDotDot,
1381 XML_mediumDashDotDot, XML_slantDashDot };
1382 mnStyle = STATIC_ARRAY_SELECT( spnStyleIds, nLineStyle, XML_none );
1383 }
1384
BorderModel(bool bDxf)1385 BorderModel::BorderModel( bool bDxf ) :
1386 maLeft( bDxf ),
1387 maRight( bDxf ),
1388 maTop( bDxf ),
1389 maBottom( bDxf ),
1390 maDiagonal( bDxf ),
1391 mbDiagTLtoBR( false ),
1392 mbDiagBLtoTR( false )
1393 {
1394 }
1395
ApiBorderData()1396 ApiBorderData::ApiBorderData() :
1397 mbBorderUsed( false ),
1398 mbDiagUsed( false )
1399 {
1400 }
1401
hasAnyOuterBorder() const1402 bool ApiBorderData::hasAnyOuterBorder() const
1403 {
1404 return
1405 ( lcl_isBorder( maTop ) && maTop.OuterLineWidth > 0 ) ||
1406 ( lcl_isBorder( maBottom ) && maBottom.OuterLineWidth > 0 ) ||
1407 ( lcl_isBorder( maLeft ) && maLeft.OuterLineWidth > 0 ) ||
1408 ( lcl_isBorder( maRight ) && maRight.OuterLineWidth > 0 );
1409 }
1410
1411 namespace {
1412
lclSetBorderLineWidth(BorderLine & rBorderLine,sal_Int16 nOuter,sal_Int16 nDist=API_LINE_NONE,sal_Int16 nInner=API_LINE_NONE)1413 void lclSetBorderLineWidth( BorderLine& rBorderLine,
1414 sal_Int16 nOuter, sal_Int16 nDist = API_LINE_NONE, sal_Int16 nInner = API_LINE_NONE )
1415 {
1416 rBorderLine.OuterLineWidth = nOuter;
1417 rBorderLine.LineDistance = nDist;
1418 rBorderLine.InnerLineWidth = nInner;
1419 }
1420
1421 } // namespace
1422
Border(const WorkbookHelper & rHelper,bool bDxf)1423 Border::Border( const WorkbookHelper& rHelper, bool bDxf ) :
1424 WorkbookHelper( rHelper ),
1425 maModel( bDxf ),
1426 mbDxf( bDxf )
1427 {
1428 }
1429
importBorder(const AttributeList & rAttribs)1430 void Border::importBorder( const AttributeList& rAttribs )
1431 {
1432 maModel.mbDiagTLtoBR = rAttribs.getBool( XML_diagonalDown, false );
1433 maModel.mbDiagBLtoTR = rAttribs.getBool( XML_diagonalUp, false );
1434 }
1435
importStyle(sal_Int32 nElement,const AttributeList & rAttribs)1436 void Border::importStyle( sal_Int32 nElement, const AttributeList& rAttribs )
1437 {
1438 if( BorderLineModel* pBorderLine = getBorderLine( nElement ) )
1439 {
1440 pBorderLine->mnStyle = rAttribs.getToken( XML_style, XML_none );
1441 pBorderLine->mbUsed = true;
1442 }
1443 }
1444
importColor(sal_Int32 nElement,const AttributeList & rAttribs)1445 void Border::importColor( sal_Int32 nElement, const AttributeList& rAttribs )
1446 {
1447 if( BorderLineModel* pBorderLine = getBorderLine( nElement ) )
1448 pBorderLine->maColor.importColor( rAttribs );
1449 }
1450
importBorder(SequenceInputStream & rStrm)1451 void Border::importBorder( SequenceInputStream& rStrm )
1452 {
1453 sal_uInt8 nFlags = rStrm.readuInt8();
1454 maModel.mbDiagTLtoBR = getFlag( nFlags, BIFF12_BORDER_DIAG_TLBR );
1455 maModel.mbDiagBLtoTR = getFlag( nFlags, BIFF12_BORDER_DIAG_BLTR );
1456 maModel.maTop.setBiffStyle( rStrm.readuInt16() );
1457 rStrm >> maModel.maTop.maColor;
1458 maModel.maBottom.setBiffStyle( rStrm.readuInt16() );
1459 rStrm >> maModel.maBottom.maColor;
1460 maModel.maLeft.setBiffStyle( rStrm.readuInt16() );
1461 rStrm >> maModel.maLeft.maColor;
1462 maModel.maRight.setBiffStyle( rStrm.readuInt16() );
1463 rStrm >> maModel.maRight.maColor;
1464 maModel.maDiagonal.setBiffStyle( rStrm.readuInt16() );
1465 rStrm >> maModel.maDiagonal.maColor;
1466 }
1467
importDxfBorder(sal_Int32 nElement,SequenceInputStream & rStrm)1468 void Border::importDxfBorder( sal_Int32 nElement, SequenceInputStream& rStrm )
1469 {
1470 SAL_WARN_IF( !mbDxf, "sc", "Border::importDxfBorder - missing conditional formatting flag" );
1471 if( BorderLineModel* pBorderLine = getBorderLine( nElement ) )
1472 {
1473 sal_uInt16 nStyle;
1474 rStrm >> pBorderLine->maColor;
1475 nStyle = rStrm.readuInt16();
1476 pBorderLine->setBiffStyle( nStyle );
1477 pBorderLine->mbUsed = true;
1478 }
1479 }
1480
finalizeImport(bool bRTL)1481 void Border::finalizeImport( bool bRTL )
1482 {
1483 if ( bRTL )
1484 {
1485 BorderLineModel aTmp = maModel.maLeft;
1486 maModel.maLeft = maModel.maRight;
1487 maModel.maRight = aTmp;
1488 }
1489 maApiData.mbBorderUsed = maModel.maLeft.mbUsed || maModel.maRight.mbUsed || maModel.maTop.mbUsed || maModel.maBottom.mbUsed;
1490 maApiData.mbDiagUsed = maModel.maDiagonal.mbUsed;
1491
1492 convertBorderLine( maApiData.maLeft, maModel.maLeft );
1493 convertBorderLine( maApiData.maRight, maModel.maRight );
1494 convertBorderLine( maApiData.maTop, maModel.maTop );
1495 convertBorderLine( maApiData.maBottom, maModel.maBottom );
1496
1497 if( maModel.mbDiagTLtoBR )
1498 convertBorderLine( maApiData.maTLtoBR, maModel.maDiagonal );
1499 if( maModel.mbDiagBLtoTR )
1500 convertBorderLine( maApiData.maBLtoTR, maModel.maDiagonal );
1501 }
1502
fillToItemSet(SfxItemSet & rItemSet,bool bSkipPoolDefs) const1503 void Border::fillToItemSet( SfxItemSet& rItemSet, bool bSkipPoolDefs ) const
1504 {
1505 if( maApiData.mbBorderUsed )
1506 {
1507 SvxBoxItem aBoxItem( ATTR_BORDER );
1508 ::editeng::SvxBorderLine aLine;
1509
1510 if (SvxBoxItem::LineToSvxLine(maApiData.maLeft, aLine, false))
1511 {
1512 aBoxItem.SetLine( &aLine, SvxBoxItemLine::LEFT );
1513 }
1514 if (SvxBoxItem::LineToSvxLine(maApiData.maRight, aLine, false))
1515 {
1516 aBoxItem.SetLine( &aLine, SvxBoxItemLine::RIGHT );
1517 }
1518 if (SvxBoxItem::LineToSvxLine(maApiData.maTop, aLine, false))
1519 {
1520 aBoxItem.SetLine( &aLine, SvxBoxItemLine::TOP );
1521 }
1522 if (SvxBoxItem::LineToSvxLine(maApiData.maBottom, aLine, false))
1523 {
1524 aBoxItem.SetLine( &aLine, SvxBoxItemLine::BOTTOM );
1525 }
1526 ScfTools::PutItem( rItemSet, aBoxItem, bSkipPoolDefs );
1527 }
1528 if ( !maApiData.mbDiagUsed )
1529 return;
1530
1531 SvxLineItem aTLBRItem( ATTR_BORDER_TLBR );
1532 SvxLineItem aBLTRItem( ATTR_BORDER_BLTR );
1533 ::editeng::SvxBorderLine aLine;
1534 if (SvxBoxItem::LineToSvxLine(maApiData.maTLtoBR, aLine, false))
1535 {
1536 aTLBRItem.SetLine( &aLine );
1537 }
1538 if (SvxBoxItem::LineToSvxLine(maApiData.maBLtoTR, aLine, false))
1539 {
1540 aBLTRItem.SetLine( &aLine );
1541 }
1542 ScfTools::PutItem( rItemSet, aTLBRItem, bSkipPoolDefs );
1543 ScfTools::PutItem( rItemSet, aBLTRItem, bSkipPoolDefs );
1544 }
1545
getBorderLine(sal_Int32 nElement)1546 BorderLineModel* Border::getBorderLine( sal_Int32 nElement )
1547 {
1548 switch( nElement )
1549 {
1550 case XLS_TOKEN( left ): return &maModel.maLeft;
1551 case XLS_TOKEN( start ): return &maModel.maLeft;
1552 case XLS_TOKEN( right ): return &maModel.maRight;
1553 case XLS_TOKEN( end ): return &maModel.maRight;
1554 case XLS_TOKEN( top ): return &maModel.maTop;
1555 case XLS_TOKEN( bottom ): return &maModel.maBottom;
1556 case XLS_TOKEN( diagonal ): return &maModel.maDiagonal;
1557 }
1558 return nullptr;
1559 }
1560
convertBorderLine(BorderLine2 & rBorderLine,const BorderLineModel & rModel)1561 bool Border::convertBorderLine( BorderLine2& rBorderLine, const BorderLineModel& rModel )
1562 {
1563 // Document: sc/qa/unit/data/README.cellborders
1564
1565 rBorderLine.Color = sal_Int32(rModel.maColor.getColor( getBaseFilter().getGraphicHelper(), API_RGB_BLACK ));
1566 switch( rModel.mnStyle )
1567 {
1568 case XML_dashDot:
1569 lclSetBorderLineWidth( rBorderLine, API_LINE_THIN );
1570 rBorderLine.LineStyle = BorderLineStyle::DASH_DOT;
1571 break;
1572 case XML_dashDotDot:
1573 lclSetBorderLineWidth( rBorderLine, API_LINE_THIN );
1574 rBorderLine.LineStyle = BorderLineStyle::DASH_DOT_DOT;
1575 break;
1576 case XML_dashed:
1577 lclSetBorderLineWidth( rBorderLine, API_LINE_THIN );
1578 rBorderLine.LineStyle = BorderLineStyle::FINE_DASHED;
1579 break;
1580 case XML_dotted:
1581 lclSetBorderLineWidth( rBorderLine, API_LINE_THIN );
1582 rBorderLine.LineStyle = BorderLineStyle::DOTTED;
1583 break;
1584 case XML_double:
1585 lclSetBorderLineWidth( rBorderLine, 10, 15, 10 );
1586 rBorderLine.LineStyle = BorderLineStyle::DOUBLE_THIN;
1587 break;
1588 case XML_hair: lclSetBorderLineWidth( rBorderLine, API_LINE_HAIR ); break;
1589 case XML_medium: lclSetBorderLineWidth( rBorderLine, API_LINE_MEDIUM ); break;
1590 case XML_mediumDashDot:
1591 lclSetBorderLineWidth( rBorderLine, API_LINE_MEDIUM );
1592 rBorderLine.LineStyle = BorderLineStyle::DASH_DOT;
1593 break;
1594 case XML_mediumDashDotDot:
1595 lclSetBorderLineWidth( rBorderLine, API_LINE_MEDIUM );
1596 rBorderLine.LineStyle = BorderLineStyle::DASH_DOT_DOT;
1597 break;
1598 case XML_mediumDashed:
1599 lclSetBorderLineWidth( rBorderLine, API_LINE_MEDIUM );
1600 rBorderLine.LineStyle = BorderLineStyle::DASHED;
1601 break;
1602 case XML_none: lclSetBorderLineWidth( rBorderLine, API_LINE_NONE ); break;
1603 case XML_slantDashDot:
1604 lclSetBorderLineWidth( rBorderLine, API_LINE_MEDIUM );
1605 rBorderLine.LineStyle = BorderLineStyle::FINE_DASHED;
1606 break;
1607 case XML_thick: lclSetBorderLineWidth( rBorderLine, API_LINE_THICK ); break;
1608 case XML_thin: lclSetBorderLineWidth( rBorderLine, API_LINE_THIN ); break;
1609 default: lclSetBorderLineWidth( rBorderLine, API_LINE_NONE ); break;
1610 }
1611 return rModel.mbUsed;
1612 }
1613
PatternFillModel(bool bDxf)1614 PatternFillModel::PatternFillModel( bool bDxf ) :
1615 mnPattern( XML_none ),
1616 mbPattColorUsed( !bDxf ),
1617 mbFillColorUsed( !bDxf ),
1618 mbPatternUsed( !bDxf )
1619 {
1620 maPatternColor.setIndexed( OOX_COLOR_WINDOWTEXT );
1621 maFillColor.setIndexed( OOX_COLOR_WINDOWBACK );
1622 }
1623
setBiffPattern(sal_Int32 nPattern)1624 void PatternFillModel::setBiffPattern( sal_Int32 nPattern )
1625 {
1626 static const sal_Int32 spnPatternIds[] = {
1627 XML_none, XML_solid, XML_mediumGray, XML_darkGray,
1628 XML_lightGray, XML_darkHorizontal, XML_darkVertical, XML_darkDown,
1629 XML_darkUp, XML_darkGrid, XML_darkTrellis, XML_lightHorizontal,
1630 XML_lightVertical, XML_lightDown, XML_lightUp, XML_lightGrid,
1631 XML_lightTrellis, XML_gray125, XML_gray0625 };
1632 mnPattern = STATIC_ARRAY_SELECT( spnPatternIds, nPattern, XML_none );
1633 }
1634
GradientFillModel()1635 GradientFillModel::GradientFillModel() :
1636 mnType( XML_linear ),
1637 mfAngle( 0.0 ),
1638 mfLeft( 0.0 ),
1639 mfRight( 0.0 ),
1640 mfTop( 0.0 ),
1641 mfBottom( 0.0 )
1642 {
1643 }
1644
readGradient(SequenceInputStream & rStrm)1645 void GradientFillModel::readGradient( SequenceInputStream& rStrm )
1646 {
1647 sal_Int32 nType;
1648 nType = rStrm.readInt32();
1649 mfAngle = rStrm.readDouble();
1650 mfLeft = rStrm.readDouble();
1651 mfRight = rStrm.readDouble();
1652 mfTop = rStrm.readDouble();
1653 mfBottom = rStrm.readDouble();
1654 static const sal_Int32 spnTypes[] = { XML_linear, XML_path };
1655 mnType = STATIC_ARRAY_SELECT( spnTypes, nType, XML_TOKEN_INVALID );
1656 }
1657
readGradientStop(SequenceInputStream & rStrm,bool bDxf)1658 void GradientFillModel::readGradientStop( SequenceInputStream& rStrm, bool bDxf )
1659 {
1660 Color aColor;
1661 double fPosition;
1662 if( bDxf )
1663 {
1664 rStrm.skip( 2 );
1665 fPosition = rStrm.readDouble();
1666 rStrm >> aColor;
1667 }
1668 else
1669 {
1670 rStrm >> aColor;
1671 fPosition = rStrm.readDouble();
1672 }
1673 if( !rStrm.isEof() && (fPosition >= 0.0) )
1674 maColors[ fPosition ] = aColor;
1675 }
1676
ApiSolidFillData()1677 ApiSolidFillData::ApiSolidFillData() :
1678 mnColor( API_RGB_TRANSPARENT ),
1679 mbTransparent( true ),
1680 mbUsed( false )
1681 {
1682 }
1683
1684 namespace {
1685
lclGetMixedColorComp(sal_Int32 nPatt,sal_Int32 nFill,sal_Int32 nAlpha)1686 sal_Int32 lclGetMixedColorComp( sal_Int32 nPatt, sal_Int32 nFill, sal_Int32 nAlpha )
1687 {
1688 return ((nPatt - nFill) * nAlpha) / 0x80 + nFill;
1689 }
1690
lclGetMixedColor(::Color nPattColor,::Color nFillColor,sal_Int32 nAlpha)1691 ::Color lclGetMixedColor( ::Color nPattColor, ::Color nFillColor, sal_Int32 nAlpha )
1692 {
1693 return ::Color(
1694 lclGetMixedColorComp( nPattColor.GetRed(), nFillColor.GetRed(), nAlpha ),
1695 lclGetMixedColorComp( nPattColor.GetGreen(), nFillColor.GetGreen(), nAlpha ),
1696 lclGetMixedColorComp( nPattColor.GetBlue(), nFillColor.GetBlue(), nAlpha ) );
1697 }
1698
1699 } // namespace
1700
Fill(const WorkbookHelper & rHelper,bool bDxf)1701 Fill::Fill( const WorkbookHelper& rHelper, bool bDxf ) :
1702 WorkbookHelper( rHelper ),
1703 mbDxf( bDxf )
1704 {
1705 }
1706
importPatternFill(const AttributeList & rAttribs)1707 void Fill::importPatternFill( const AttributeList& rAttribs )
1708 {
1709 mxPatternModel = std::make_shared<PatternFillModel>( mbDxf );
1710 mxPatternModel->mnPattern = rAttribs.getToken( XML_patternType, XML_none );
1711 if( mbDxf )
1712 mxPatternModel->mbPatternUsed = rAttribs.hasAttribute( XML_patternType );
1713 }
1714
importFgColor(const AttributeList & rAttribs)1715 void Fill::importFgColor( const AttributeList& rAttribs )
1716 {
1717 OSL_ENSURE( mxPatternModel, "Fill::importFgColor - missing pattern data" );
1718 if( mxPatternModel )
1719 {
1720 mxPatternModel->maPatternColor.importColor( rAttribs );
1721 mxPatternModel->mbPattColorUsed = true;
1722 }
1723 }
1724
importBgColor(const AttributeList & rAttribs)1725 void Fill::importBgColor( const AttributeList& rAttribs )
1726 {
1727 OSL_ENSURE( mxPatternModel, "Fill::importBgColor - missing pattern data" );
1728 if( mxPatternModel )
1729 {
1730 mxPatternModel->maFillColor.importColor( rAttribs );
1731 mxPatternModel->mbFillColorUsed = true;
1732 }
1733 }
1734
importGradientFill(const AttributeList & rAttribs)1735 void Fill::importGradientFill( const AttributeList& rAttribs )
1736 {
1737 mxGradientModel = std::make_shared<GradientFillModel>();
1738 mxGradientModel->mnType = rAttribs.getToken( XML_type, XML_linear );
1739 mxGradientModel->mfAngle = rAttribs.getDouble( XML_degree, 0.0 );
1740 mxGradientModel->mfLeft = rAttribs.getDouble( XML_left, 0.0 );
1741 mxGradientModel->mfRight = rAttribs.getDouble( XML_right, 0.0 );
1742 mxGradientModel->mfTop = rAttribs.getDouble( XML_top, 0.0 );
1743 mxGradientModel->mfBottom = rAttribs.getDouble( XML_bottom, 0.0 );
1744 }
1745
importColor(const AttributeList & rAttribs,double fPosition)1746 void Fill::importColor( const AttributeList& rAttribs, double fPosition )
1747 {
1748 OSL_ENSURE( mxGradientModel, "Fill::importColor - missing gradient data" );
1749 if( mxGradientModel && (fPosition >= 0.0) )
1750 mxGradientModel->maColors[ fPosition ].importColor( rAttribs );
1751 }
1752
importFill(SequenceInputStream & rStrm)1753 void Fill::importFill( SequenceInputStream& rStrm )
1754 {
1755 SAL_WARN_IF( mbDxf, "sc", "Fill::importFill - unexpected conditional formatting flag" );
1756 sal_Int32 nPattern = rStrm.readInt32();
1757 if( nPattern == BIFF12_FILL_GRADIENT )
1758 {
1759 mxGradientModel = std::make_shared<GradientFillModel>();
1760 sal_Int32 nStopCount;
1761 rStrm.skip( 16 );
1762 mxGradientModel->readGradient( rStrm );
1763 nStopCount = rStrm.readInt32();
1764 for( sal_Int32 nStop = 0; (nStop < nStopCount) && !rStrm.isEof(); ++nStop )
1765 mxGradientModel->readGradientStop( rStrm, false );
1766 }
1767 else
1768 {
1769 mxPatternModel = std::make_shared<PatternFillModel>( mbDxf );
1770 mxPatternModel->setBiffPattern( nPattern );
1771 rStrm >> mxPatternModel->maPatternColor >> mxPatternModel->maFillColor;
1772 }
1773 }
1774
importDxfPattern(SequenceInputStream & rStrm)1775 void Fill::importDxfPattern( SequenceInputStream& rStrm )
1776 {
1777 SAL_WARN_IF( !mbDxf, "sc", "Fill::importDxfPattern - missing conditional formatting flag" );
1778 if( !mxPatternModel )
1779 mxPatternModel = std::make_shared<PatternFillModel>( mbDxf );
1780 mxPatternModel->setBiffPattern( rStrm.readuInt8() );
1781 mxPatternModel->mbPatternUsed = true;
1782 }
1783
importDxfFgColor(SequenceInputStream & rStrm)1784 void Fill::importDxfFgColor( SequenceInputStream& rStrm )
1785 {
1786 SAL_WARN_IF( !mbDxf, "sc", "Fill::importDxfFgColor - missing conditional formatting flag" );
1787 if( !mxPatternModel )
1788 mxPatternModel = std::make_shared<PatternFillModel>( mbDxf );
1789 mxPatternModel->maPatternColor.importColor( rStrm );
1790 mxPatternModel->mbPattColorUsed = true;
1791 }
1792
importDxfBgColor(SequenceInputStream & rStrm)1793 void Fill::importDxfBgColor( SequenceInputStream& rStrm )
1794 {
1795 SAL_WARN_IF( !mbDxf, "sc", "Fill::importDxfBgColor - missing conditional formatting flag" );
1796 if( !mxPatternModel )
1797 mxPatternModel = std::make_shared<PatternFillModel>( mbDxf );
1798 mxPatternModel->maFillColor.importColor( rStrm );
1799 mxPatternModel->mbFillColorUsed = true;
1800 }
1801
importDxfGradient(SequenceInputStream & rStrm)1802 void Fill::importDxfGradient( SequenceInputStream& rStrm )
1803 {
1804 SAL_WARN_IF( !mbDxf, "sc", "Fill::importDxfGradient - missing conditional formatting flag" );
1805 if( !mxGradientModel )
1806 mxGradientModel = std::make_shared<GradientFillModel>();
1807 mxGradientModel->readGradient( rStrm );
1808 }
1809
importDxfStop(SequenceInputStream & rStrm)1810 void Fill::importDxfStop( SequenceInputStream& rStrm )
1811 {
1812 SAL_WARN_IF( !mbDxf, "sc", "Fill::importDxfStop - missing conditional formatting flag" );
1813 if( !mxGradientModel )
1814 mxGradientModel = std::make_shared<GradientFillModel>();
1815 mxGradientModel->readGradientStop( rStrm, true );
1816 }
1817
finalizeImport()1818 void Fill::finalizeImport()
1819 {
1820 const GraphicHelper& rGraphicHelper = getBaseFilter().getGraphicHelper();
1821
1822 if( mxPatternModel )
1823 {
1824 // finalize the OOXML data struct
1825 PatternFillModel& rModel = *mxPatternModel;
1826 if( mbDxf )
1827 {
1828 if( rModel.mbFillColorUsed && (!rModel.mbPatternUsed || (rModel.mnPattern == XML_solid)) )
1829 {
1830 if (!rModel.mbPatternUsed)
1831 rModel.maPatternColor = rModel.maFillColor;
1832 rModel.mnPattern = XML_solid;
1833 rModel.mbPattColorUsed = rModel.mbPatternUsed = true;
1834 }
1835 else if(
1836 !rModel.mbFillColorUsed && !rModel.mbPattColorUsed &&
1837 rModel.mbPatternUsed && rModel.mnPattern == XML_solid )
1838 {
1839 rModel.mbPatternUsed = false;
1840 }
1841 }
1842
1843 // convert to API fill settings
1844 maApiData.mbUsed = rModel.mbPatternUsed;
1845 if( rModel.mnPattern == XML_none )
1846 {
1847 maApiData.mnColor = API_RGB_TRANSPARENT;
1848 maApiData.mbTransparent = true;
1849 }
1850 else
1851 {
1852 sal_Int32 nAlpha = 0x80;
1853 switch( rModel.mnPattern )
1854 {
1855 case XML_darkDown: nAlpha = 0x40; break;
1856 case XML_darkGray: nAlpha = 0x60; break;
1857 case XML_darkGrid: nAlpha = 0x40; break;
1858 case XML_darkHorizontal: nAlpha = 0x40; break;
1859 case XML_darkTrellis: nAlpha = 0x60; break;
1860 case XML_darkUp: nAlpha = 0x40; break;
1861 case XML_darkVertical: nAlpha = 0x40; break;
1862 case XML_gray0625: nAlpha = 0x08; break;
1863 case XML_gray125: nAlpha = 0x10; break;
1864 case XML_lightDown: nAlpha = 0x20; break;
1865 case XML_lightGray: nAlpha = 0x20; break;
1866 case XML_lightGrid: nAlpha = 0x38; break;
1867 case XML_lightHorizontal: nAlpha = 0x20; break;
1868 case XML_lightTrellis: nAlpha = 0x30; break;
1869 case XML_lightUp: nAlpha = 0x20; break;
1870 case XML_lightVertical: nAlpha = 0x20; break;
1871 case XML_mediumGray: nAlpha = 0x40; break;
1872 case XML_solid: nAlpha = 0x80; break;
1873 }
1874
1875 ::Color nWinTextColor = rGraphicHelper.getSystemColor( XML_windowText );
1876 ::Color nWinColor = rGraphicHelper.getSystemColor( XML_window );
1877
1878 if( !rModel.mbPattColorUsed )
1879 rModel.maPatternColor.setAuto();
1880 ::Color nPattColor = rModel.maPatternColor.getColor( rGraphicHelper, nWinTextColor );
1881
1882 if( !rModel.mbFillColorUsed )
1883 rModel.maFillColor.setAuto();
1884 ::Color nFillColor = rModel.maFillColor.getColor( rGraphicHelper, nWinColor );
1885
1886 maApiData.mnColor = lclGetMixedColor( nPattColor, nFillColor, nAlpha );
1887 maApiData.mbTransparent = false;
1888 }
1889 }
1890 else if( mxGradientModel && !mxGradientModel->maColors.empty() )
1891 {
1892 GradientFillModel& rModel = *mxGradientModel;
1893 maApiData.mbUsed = true; // no support for differential attributes
1894 GradientFillModel::ColorMap::const_iterator aIt = rModel.maColors.begin();
1895 OSL_ENSURE( !aIt->second.isAuto(), "Fill::finalizeImport - automatic gradient color" );
1896 maApiData.mnColor = aIt->second.getColor( rGraphicHelper, API_RGB_WHITE );
1897 if( ++aIt != rModel.maColors.end() )
1898 {
1899 OSL_ENSURE( !aIt->second.isAuto(), "Fill::finalizeImport - automatic gradient color" );
1900 ::Color nEndColor = aIt->second.getColor( rGraphicHelper, API_RGB_WHITE );
1901 maApiData.mnColor = lclGetMixedColor( maApiData.mnColor, nEndColor, 0x40 );
1902 maApiData.mbTransparent = false;
1903 }
1904 }
1905 }
1906
fillToItemSet(SfxItemSet & rItemSet,bool bSkipPoolDefs) const1907 void Fill::fillToItemSet( SfxItemSet& rItemSet, bool bSkipPoolDefs ) const
1908 {
1909 if( !maApiData.mbUsed )
1910 return;
1911
1912 SvxBrushItem aBrushItem( ATTR_BACKGROUND );
1913 if ( maApiData.mbTransparent )
1914 {
1915 aBrushItem.SetColor( COL_TRANSPARENT );
1916 }
1917 else
1918 {
1919 aBrushItem.SetColor( maApiData.mnColor );
1920 }
1921 ScfTools::PutItem( rItemSet, aBrushItem, bSkipPoolDefs );
1922 }
1923
XfModel()1924 XfModel::XfModel() :
1925 mnStyleXfId( -1 ),
1926 mnFontId( -1 ),
1927 mnNumFmtId( -1 ),
1928 mnBorderId( -1 ),
1929 mnFillId( -1 ),
1930 mbCellXf( true ),
1931 mbFontUsed( false ),
1932 mbNumFmtUsed( false ),
1933 mbAlignUsed( false ),
1934 mbProtUsed( false ),
1935 mbBorderUsed( false ),
1936 mbAreaUsed( false )
1937 {
1938 }
1939
AttrList(const ScPatternAttr * pDefPattern)1940 Xf::AttrList::AttrList(const ScPatternAttr* pDefPattern):
1941 mbLatinNumFmtOnly(true),
1942 mpDefPattern(pDefPattern)
1943 {}
1944
Xf(const WorkbookHelper & rHelper)1945 Xf::Xf( const WorkbookHelper& rHelper ) :
1946 WorkbookHelper( rHelper ),
1947 mnScNumFmt(0),
1948 maAlignment( rHelper ),
1949 maProtection( rHelper ),
1950 meRotationRef( css::table::CellVertJustify2::STANDARD ),
1951 mpStyleSheet( nullptr )
1952 {
1953 }
1954
importXf(const AttributeList & rAttribs,bool bCellXf)1955 void Xf::importXf( const AttributeList& rAttribs, bool bCellXf )
1956 {
1957 maModel.mbCellXf = bCellXf;
1958 // tdf#70565 Set proper default value to "0" of xfId attribute
1959 // When xfId is not exist during .xlsx import
1960 // it must have values set to "0".
1961 // This doesn't impact spreadsheets created with MS Excel,
1962 // as xfId attribute is always created during export to .xlsx
1963 // Not setting "0" value is causing wrong .xlsx import by LibreOffice,
1964 // for spreadsheets created by external applications (ex. SAP BI).
1965 if ( maModel.mbCellXf )
1966 {
1967 maModel.mnStyleXfId = rAttribs.getInteger( XML_xfId, 0 );
1968 }
1969 else
1970 {
1971 maModel.mnStyleXfId = rAttribs.getInteger( XML_xfId, -1 );
1972 }
1973 maModel.mnFontId = rAttribs.getInteger( XML_fontId, -1 );
1974 maModel.mnNumFmtId = rAttribs.getInteger( XML_numFmtId, -1 );
1975 maModel.mnBorderId = rAttribs.getInteger( XML_borderId, -1 );
1976 maModel.mnFillId = rAttribs.getInteger( XML_fillId, -1 );
1977
1978
1979 /* Default value of the apply*** attributes is dependent on context:
1980 true in cellStyleXfs element, false in cellXfs element... */
1981 maModel.mbAlignUsed = rAttribs.getBool( XML_applyAlignment, !maModel.mbCellXf );
1982 maModel.mbProtUsed = rAttribs.getBool( XML_applyProtection, !maModel.mbCellXf );
1983 maModel.mbFontUsed = rAttribs.getBool( XML_applyFont, !maModel.mbCellXf );
1984 maModel.mbNumFmtUsed = rAttribs.getBool( XML_applyNumberFormat, !maModel.mbCellXf );
1985 maModel.mbBorderUsed = rAttribs.getBool( XML_applyBorder, !maModel.mbCellXf );
1986 maModel.mbAreaUsed = rAttribs.getBool( XML_applyFill, !maModel.mbCellXf );
1987 }
1988
importAlignment(const AttributeList & rAttribs)1989 void Xf::importAlignment( const AttributeList& rAttribs )
1990 {
1991 maAlignment.importAlignment( rAttribs );
1992 }
1993
importProtection(const AttributeList & rAttribs)1994 void Xf::importProtection( const AttributeList& rAttribs )
1995 {
1996 maProtection.importProtection( rAttribs );
1997 }
1998
importXf(SequenceInputStream & rStrm,bool bCellXf)1999 void Xf::importXf( SequenceInputStream& rStrm, bool bCellXf )
2000 {
2001 maModel.mbCellXf = bCellXf;
2002 maModel.mnStyleXfId = rStrm.readuInt16();
2003 maModel.mnNumFmtId = rStrm.readuInt16();
2004 maModel.mnFontId = rStrm.readuInt16();
2005 maModel.mnFillId = rStrm.readuInt16();
2006 maModel.mnBorderId = rStrm.readuInt16();
2007 sal_uInt32 nFlags = rStrm.readuInt32();
2008 maAlignment.setBiff12Data( nFlags );
2009 maProtection.setBiff12Data( nFlags );
2010 // used flags, see comments in Xf::setBiffUsedFlags()
2011 sal_uInt16 nUsedFlags = rStrm.readuInt16();
2012 maModel.mbFontUsed = maModel.mbCellXf == getFlag( nUsedFlags, BIFF12_XF_FONT_USED );
2013 maModel.mbNumFmtUsed = maModel.mbCellXf == getFlag( nUsedFlags, BIFF12_XF_NUMFMT_USED );
2014 maModel.mbAlignUsed = maModel.mbCellXf == getFlag( nUsedFlags, BIFF12_XF_ALIGN_USED );
2015 maModel.mbProtUsed = maModel.mbCellXf == getFlag( nUsedFlags, BIFF12_XF_PROT_USED );
2016 maModel.mbBorderUsed = maModel.mbCellXf == getFlag( nUsedFlags, BIFF12_XF_BORDER_USED );
2017 maModel.mbAreaUsed = maModel.mbCellXf == getFlag( nUsedFlags, BIFF12_XF_AREA_USED );
2018 }
2019
finalizeImport()2020 void Xf::finalizeImport()
2021 {
2022 // alignment and protection
2023 maAlignment.finalizeImport();
2024 maProtection.finalizeImport();
2025 }
2026
getFont() const2027 FontRef Xf::getFont() const
2028 {
2029 return getStyles().getFont( maModel.mnFontId );
2030 }
2031
applyPatternToAttrList(AttrList & rAttrs,SCROW nRow1,SCROW nRow2,sal_Int32 nNumFmtId)2032 void Xf::applyPatternToAttrList( AttrList& rAttrs, SCROW nRow1, SCROW nRow2, sal_Int32 nNumFmtId )
2033 {
2034 createPattern();
2035 ScPatternAttr& rPat = *mpPattern;
2036 ScDocumentImport& rDocImport = getDocImport();
2037 ScDocument& rDoc = getScDocument();
2038 if ( isCellXf() )
2039 {
2040 StylesBuffer& rStyles = getStyles();
2041 rStyles.createCellStyle( maModel.mnStyleXfId );
2042
2043 mpStyleSheet = rStyles.getCellStyleSheet( maModel.mnStyleXfId );
2044 if ( mpStyleSheet )
2045 {
2046 //rDoc.ApplySelectionStyle( static_cast<ScStyleSheet&>(*mpStyleSheet), rMarkData );
2047 rPat.SetStyleSheet(mpStyleSheet, false);
2048 }
2049 else
2050 {
2051 ScStyleSheetPool* pStylePool = rDoc.GetStyleSheetPool();
2052 if (pStylePool)
2053 {
2054 ScStyleSheet* pStyleSheet = static_cast<ScStyleSheet*>(
2055 pStylePool->Find(
2056 ScResId(STR_STYLENAME_STANDARD), SfxStyleFamily::Para));
2057
2058 if (pStyleSheet)
2059 rPat.SetStyleSheet( pStyleSheet, false );
2060 }
2061 }
2062 }
2063 if ( nNumFmtId >= 0 )
2064 {
2065 ScPatternAttr aNumPat(rDoc.GetPool());
2066 mnScNumFmt = getStyles().writeNumFmtToItemSet( aNumPat.GetItemSet(), nNumFmtId, false );
2067 rPat.GetItemSet().Put(aNumPat.GetItemSet());
2068 }
2069
2070 if (!rDocImport.isLatinScript(mnScNumFmt))
2071 rAttrs.mbLatinNumFmtOnly = false;
2072
2073 if (!rPat.GetStyleName())
2074 return;
2075
2076 // Check for a gap between the last entry and this one.
2077 bool bHasGap = false;
2078 if (rAttrs.maAttrs.empty() && nRow1 > 0)
2079 // First attribute range doesn't start at row 0.
2080 bHasGap = true;
2081
2082 if (!rAttrs.maAttrs.empty() && rAttrs.maAttrs.back().nEndRow + 1 < nRow1)
2083 bHasGap = true;
2084
2085 if (bHasGap)
2086 {
2087 // Fill this gap with the default pattern.
2088 ScAttrEntry aEntry;
2089 aEntry.nEndRow = nRow1 - 1;
2090 aEntry.pPattern = &rDoc.GetPool()->Put(*rAttrs.mpDefPattern);
2091 rAttrs.maAttrs.push_back(aEntry);
2092
2093 // Check if the default pattern is 'General'.
2094 if (!rDocImport.isLatinScript(*aEntry.pPattern))
2095 rAttrs.mbLatinNumFmtOnly = false;
2096 }
2097
2098 ScAttrEntry aEntry;
2099 aEntry.nEndRow = nRow2;
2100 aEntry.pPattern = &rDoc.GetPool()->Put(rPat);
2101 rAttrs.maAttrs.push_back(aEntry);
2102
2103 if (!rDocImport.isLatinScript(*aEntry.pPattern))
2104 rAttrs.mbLatinNumFmtOnly = false;
2105 }
2106
writeToDoc(ScDocumentImport & rDoc,const ScRange & rRange)2107 void Xf::writeToDoc( ScDocumentImport& rDoc, const ScRange& rRange )
2108 {
2109 const StylesBuffer& rStyles = getStyles();
2110
2111 if (isCellXf())
2112 {
2113 // Cell style name.
2114 OUString aStyleName = rStyles.createCellStyle(maModel.mnStyleXfId);
2115
2116 ScStyleSheet* pStyleSheet =
2117 static_cast<ScStyleSheet*>(
2118 rDoc.getDoc().GetStyleSheetPool()->Find(aStyleName, SfxStyleFamily::Para));
2119
2120 if (pStyleSheet)
2121 {
2122 rDoc.getDoc().ApplyStyleAreaTab(
2123 rRange.aStart.Col(), rRange.aStart.Row(), rRange.aEnd.Col(), rRange.aEnd.Row(), rRange.aStart.Tab(),
2124 *pStyleSheet);
2125 }
2126 }
2127
2128 const ScPatternAttr& rAttr = createPattern();
2129 rDoc.getDoc().ApplyPatternAreaTab(
2130 rRange.aStart.Col(), rRange.aStart.Row(), rRange.aEnd.Col(), rRange.aEnd.Row(), rRange.aStart.Tab(), rAttr);
2131 }
2132
2133 const ::ScPatternAttr&
createPattern(bool bSkipPoolDefs)2134 Xf::createPattern( bool bSkipPoolDefs )
2135 {
2136 if( mpPattern )
2137 return *mpPattern;
2138 mpPattern.reset( new ::ScPatternAttr( getScDocument().GetPool() ) );
2139 SfxItemSet& rItemSet = mpPattern->GetItemSet();
2140 /* Enables the used flags, if the formatting attributes differ from the
2141 style XF. In cell XFs Excel uses the cell attributes, if they differ
2142 from the parent style XF (even if the used flag is switched off).
2143 #109899# ...or if the respective flag is not set in parent style XF.
2144 */
2145 StylesBuffer& rStyles = getStyles();
2146
2147 const Xf* pStyleXf = isCellXf() ? rStyles.getStyleXf( maModel.mnStyleXfId ).get() : nullptr;
2148 if( pStyleXf && !mpStyleSheet )
2149 {
2150 rStyles.createCellStyle( maModel.mnStyleXfId );
2151 mpStyleSheet = rStyles.getCellStyleSheet( maModel.mnStyleXfId );
2152 OSL_ENSURE( mpStyleSheet, "Xf::createPattern - no parentStyle created" );
2153
2154 const XfModel& rStyleData = pStyleXf->maModel;
2155 if( !maModel.mbFontUsed )
2156 maModel.mbFontUsed = !rStyleData.mbFontUsed || (maModel.mnFontId != rStyleData.mnFontId);
2157 if( !maModel.mbNumFmtUsed )
2158 maModel.mbNumFmtUsed = !rStyleData.mbNumFmtUsed || (maModel.mnNumFmtId != rStyleData.mnNumFmtId);
2159 if( !maModel.mbAlignUsed )
2160 maModel.mbAlignUsed = !rStyleData.mbAlignUsed || !(maAlignment.getApiData() == pStyleXf->maAlignment.getApiData());
2161 if( !maModel.mbProtUsed )
2162 maModel.mbProtUsed = !rStyleData.mbProtUsed || !(maProtection.getApiData() == pStyleXf->maProtection.getApiData());
2163 if( !maModel.mbBorderUsed )
2164 maModel.mbBorderUsed = !rStyleData.mbBorderUsed || !StylesBuffer::equalBorders( maModel.mnBorderId, rStyleData.mnBorderId );
2165 if( !maModel.mbAreaUsed )
2166 maModel.mbAreaUsed = !rStyleData.mbAreaUsed || !StylesBuffer::equalFills( maModel.mnFillId, rStyleData.mnFillId );
2167 }
2168 // cell protection
2169 if( maModel.mbProtUsed )
2170 {
2171 maProtection.fillToItemSet( rItemSet, bSkipPoolDefs );
2172 }
2173
2174 // font
2175 if( maModel.mbFontUsed )
2176 {
2177 rStyles.writeFontToItemSet( rItemSet, maModel.mnFontId, bSkipPoolDefs );
2178 }
2179
2180 // value format
2181 if( maModel.mbNumFmtUsed )
2182 {
2183 mnScNumFmt = rStyles.writeNumFmtToItemSet( rItemSet, maModel.mnNumFmtId, bSkipPoolDefs );
2184 }
2185 // alignment
2186 if( maModel.mbAlignUsed )
2187 {
2188 maAlignment.fillToItemSet( rItemSet, bSkipPoolDefs );
2189 }
2190
2191 // border
2192 if( maModel.mbBorderUsed )
2193 {
2194 rStyles.writeBorderToItemSet( rItemSet, maModel.mnBorderId, bSkipPoolDefs );
2195 }
2196
2197 // area
2198 if( maModel.mbAreaUsed )
2199 {
2200 rStyles.writeFillToItemSet( rItemSet, maModel.mnFillId, bSkipPoolDefs );
2201 }
2202
2203 /* #i38709# Decide which rotation reference mode to use. If any outer
2204 border line of the cell is set (either explicitly or via cell style),
2205 and the cell contents are rotated, set rotation reference to bottom of
2206 cell. This causes the borders to be painted rotated with the text. */
2207 if( const Alignment* pAlignment = maModel.mbAlignUsed ? &maAlignment : (pStyleXf ? &pStyleXf->maAlignment : nullptr) )
2208 {
2209 SvxRotateMode eRotateMode = SVX_ROTATE_MODE_STANDARD;
2210 sal_Int32 nBorderId = maModel.mbBorderUsed ? maModel.mnBorderId : (pStyleXf ? pStyleXf->maModel.mnBorderId : -1);
2211 if( const Border* pBorder = rStyles.getBorder( nBorderId ).get() )
2212 {
2213 if( (pAlignment->getApiData().mnRotation) && pBorder->getApiData().hasAnyOuterBorder() )
2214 {
2215 meRotationRef = css::table::CellVertJustify2::BOTTOM;
2216 eRotateMode = SVX_ROTATE_MODE_BOTTOM;
2217 }
2218 }
2219 ScfTools::PutItem( rItemSet, SvxRotateModeItem( eRotateMode, ATTR_ROTATE_MODE ), bSkipPoolDefs );
2220 }
2221
2222 return *mpPattern;
2223 }
2224
Dxf(const WorkbookHelper & rHelper)2225 Dxf::Dxf( const WorkbookHelper& rHelper ) :
2226 WorkbookHelper( rHelper )
2227 {
2228 }
2229
createFont(bool bAlwaysNew)2230 FontRef const & Dxf::createFont( bool bAlwaysNew )
2231 {
2232 if( bAlwaysNew || !mxFont )
2233 mxFont = std::make_shared<Font>( *this, true );
2234 return mxFont;
2235 }
2236
createBorder(bool bAlwaysNew)2237 BorderRef const & Dxf::createBorder( bool bAlwaysNew )
2238 {
2239 if( bAlwaysNew || !mxBorder )
2240 mxBorder = std::make_shared<Border>( *this, true );
2241 return mxBorder;
2242 }
2243
createFill(bool bAlwaysNew)2244 FillRef const & Dxf::createFill( bool bAlwaysNew )
2245 {
2246 if( bAlwaysNew || !mxFill )
2247 mxFill = std::make_shared<Fill>( *this, true );
2248 return mxFill;
2249 }
2250
importNumFmt(const AttributeList & rAttribs)2251 void Dxf::importNumFmt( const AttributeList& rAttribs )
2252 {
2253 // don't propagate number formats defined in Dxf entries
2254 // they can have the same id ( but different format codes ) as those
2255 // defined globally earlier. We discard the id defined in XML_numFmtId
2256 // and generate one ourselves ( this assumes that the normal numberformat
2257 // import has already taken place )
2258 sal_Int32 nNumFmtId = getStyles().nextFreeNumFmtId();
2259 OUString aFmtCode = rAttribs.getXString( XML_formatCode, OUString() );
2260 mxNumFmt = getStyles().createNumFmt( nNumFmtId, aFmtCode );
2261 }
2262
importDxf(SequenceInputStream & rStrm)2263 void Dxf::importDxf( SequenceInputStream& rStrm )
2264 {
2265 sal_Int32 nNumFmtId = -1;
2266 OUString aFmtCode;
2267 sal_uInt16 nRecCount;
2268 rStrm.skip( 4 ); // flags
2269 nRecCount = rStrm.readuInt16();
2270 for( sal_uInt16 nRec = 0; !rStrm.isEof() && (nRec < nRecCount); ++nRec )
2271 {
2272 sal_uInt16 nSubRecId, nSubRecSize;
2273 sal_Int64 nRecEnd = rStrm.tell();
2274 nSubRecId = rStrm.readuInt16();
2275 nSubRecSize = rStrm.readuInt16();
2276 nRecEnd += nSubRecSize;
2277 switch( nSubRecId )
2278 {
2279 case BIFF12_DXF_FILL_PATTERN: createFill( false )->importDxfPattern( rStrm ); break;
2280 case BIFF12_DXF_FILL_FGCOLOR: createFill( false )->importDxfFgColor( rStrm ); break;
2281 case BIFF12_DXF_FILL_BGCOLOR: createFill( false )->importDxfBgColor( rStrm ); break;
2282 case BIFF12_DXF_FILL_GRADIENT: createFill( false )->importDxfGradient( rStrm ); break;
2283 case BIFF12_DXF_FILL_STOP: createFill( false )->importDxfStop( rStrm ); break;
2284 case BIFF12_DXF_FONT_COLOR: createFont( false )->importDxfColor( rStrm ); break;
2285 case BIFF12_DXF_BORDER_TOP: createBorder( false )->importDxfBorder( XLS_TOKEN( top ), rStrm ); break;
2286 case BIFF12_DXF_BORDER_BOTTOM: createBorder( false )->importDxfBorder( XLS_TOKEN( bottom ), rStrm ); break;
2287 case BIFF12_DXF_BORDER_LEFT: createBorder( false )->importDxfBorder( XLS_TOKEN( left ), rStrm ); break;
2288 case BIFF12_DXF_BORDER_RIGHT: createBorder( false )->importDxfBorder( XLS_TOKEN( right ), rStrm ); break;
2289 case BIFF12_DXF_FONT_NAME: createFont( false )->importDxfName( rStrm ); break;
2290 case BIFF12_DXF_FONT_WEIGHT: createFont( false )->importDxfWeight( rStrm ); break;
2291 case BIFF12_DXF_FONT_UNDERLINE: createFont( false )->importDxfUnderline( rStrm ); break;
2292 case BIFF12_DXF_FONT_ESCAPEMENT: createFont( false )->importDxfEscapement( rStrm ); break;
2293 case BIFF12_DXF_FONT_ITALIC: createFont( false )->importDxfFlag( XML_i, rStrm ); break;
2294 case BIFF12_DXF_FONT_STRIKE: createFont( false )->importDxfFlag( XML_strike, rStrm ); break;
2295 case BIFF12_DXF_FONT_OUTLINE: createFont( false )->importDxfFlag( XML_outline, rStrm ); break;
2296 case BIFF12_DXF_FONT_SHADOW: createFont( false )->importDxfFlag( XML_shadow, rStrm ); break;
2297 case BIFF12_DXF_FONT_HEIGHT: createFont( false )->importDxfHeight( rStrm ); break;
2298 case BIFF12_DXF_FONT_SCHEME: createFont( false )->importDxfScheme( rStrm ); break;
2299 case BIFF12_DXF_NUMFMT_CODE: aFmtCode = BiffHelper::readString( rStrm, false ); break;
2300 case BIFF12_DXF_NUMFMT_ID: nNumFmtId = rStrm.readuInt16(); break;
2301 }
2302 rStrm.seek( nRecEnd );
2303 }
2304 OSL_ENSURE( !rStrm.isEof() && (rStrm.getRemaining() == 0), "Dxf::importDxf - unexpected remaining data" );
2305 mxNumFmt = getStyles().createNumFmt( nNumFmtId, aFmtCode );
2306 }
2307
finalizeImport()2308 void Dxf::finalizeImport()
2309 {
2310 if( mxFont )
2311 mxFont->finalizeImport();
2312 bool bRTL = false;
2313 // number format already finalized by the number formats buffer
2314 if( mxAlignment )
2315 {
2316 mxAlignment->finalizeImport();
2317 // how do we detect RTL when text dir is OOX_XF_CONTEXT? ( seems you
2318 // would need access to the cell content, which we don't here )
2319 if ( mxAlignment->getModel().mnTextDir == OOX_XF_TEXTDIR_RTL )
2320 bRTL = true;
2321 }
2322 if( mxProtection )
2323 mxProtection->finalizeImport();
2324 if( mxBorder )
2325 {
2326 mxBorder->finalizeImport( bRTL );
2327 }
2328 if( mxFill )
2329 mxFill->finalizeImport();
2330 }
2331
fillToItemSet(SfxItemSet & rSet) const2332 void Dxf::fillToItemSet( SfxItemSet& rSet ) const
2333 {
2334 if (mxFont)
2335 mxFont->fillToItemSet(rSet, false);
2336 if (mxNumFmt)
2337 mxNumFmt->fillToItemSet(rSet);
2338 if (mxAlignment)
2339 mxAlignment->fillToItemSet(rSet);
2340 if (mxProtection)
2341 mxProtection->fillToItemSet(rSet);
2342 if (mxBorder)
2343 mxBorder->fillToItemSet(rSet);
2344 if (mxFill)
2345 mxFill->fillToItemSet(rSet);
2346 }
2347
2348 namespace {
2349
2350 const char* const sppcStyleNames[] =
2351 {
2352 "Normal",
2353 "RowLevel_", // outline level will be appended
2354 "ColLevel_", // outline level will be appended
2355 "Comma",
2356 "Currency",
2357 "Percent",
2358 "Comma [0]", // new in BIFF4
2359 "Currency [0]",
2360 "Hyperlink", // new in BIFF8
2361 "Followed Hyperlink",
2362 "Note", // new in OOX
2363 "Warning Text",
2364 nullptr,
2365 nullptr,
2366 nullptr,
2367 "Title",
2368 "Heading 1",
2369 "Heading 2",
2370 "Heading 3",
2371 "Heading 4",
2372 "Input",
2373 "Output",
2374 "Calculation",
2375 "Check Cell",
2376 "Linked Cell",
2377 "Total",
2378 "Good",
2379 "Bad",
2380 "Neutral",
2381 "Accent1",
2382 "20% - Accent1",
2383 "40% - Accent1",
2384 "60% - Accent1",
2385 "Accent2",
2386 "20% - Accent2",
2387 "40% - Accent2",
2388 "60% - Accent2",
2389 "Accent3",
2390 "20% - Accent3",
2391 "40% - Accent3",
2392 "60% - Accent3",
2393 "Accent4",
2394 "20% - Accent4",
2395 "40% - Accent4",
2396 "60% - Accent4",
2397 "Accent5",
2398 "20% - Accent5",
2399 "40% - Accent5",
2400 "60% - Accent5",
2401 "Accent6",
2402 "20% - Accent6",
2403 "40% - Accent6",
2404 "60% - Accent6",
2405 "Explanatory Text"
2406 };
2407 const sal_Int32 snStyleNamesCount = static_cast< sal_Int32 >( SAL_N_ELEMENTS( sppcStyleNames ) );
2408
lclGetBuiltinStyleName(sal_Int32 nBuiltinId,std::u16string_view rName,sal_Int32 nLevel=0)2409 OUString lclGetBuiltinStyleName( sal_Int32 nBuiltinId, std::u16string_view rName, sal_Int32 nLevel = 0 )
2410 {
2411 OSL_ENSURE( (0 <= nBuiltinId) && (nBuiltinId < snStyleNamesCount), "lclGetBuiltinStyleName - unknown built-in style" );
2412 OUStringBuffer aStyleName("Excel Built-in ");
2413 if( (0 <= nBuiltinId) && (nBuiltinId < snStyleNamesCount) && (sppcStyleNames[ nBuiltinId ] != nullptr) )
2414 aStyleName.appendAscii( sppcStyleNames[ nBuiltinId ] );
2415 else if( !rName.empty() )
2416 aStyleName.append( rName );
2417 else
2418 aStyleName.append( nBuiltinId );
2419 if( (nBuiltinId == OOX_STYLE_ROWLEVEL) || (nBuiltinId == OOX_STYLE_COLLEVEL) )
2420 aStyleName.append( nLevel );
2421 return aStyleName.makeStringAndClear();
2422 }
2423
lclCreateStyleName(const CellStyleModel & rModel)2424 OUString lclCreateStyleName( const CellStyleModel& rModel )
2425 {
2426 return rModel.mbBuiltin ? lclGetBuiltinStyleName( rModel.mnBuiltinId, rModel.maName, rModel.mnLevel ) : rModel.maName;
2427 }
2428
2429 } // namespace
2430
CellStyleModel()2431 CellStyleModel::CellStyleModel() :
2432 mnXfId( -1 ),
2433 mnBuiltinId( -1 ),
2434 mnLevel( 0 ),
2435 mbBuiltin( false ),
2436 mbCustom( false ),
2437 mbHidden( false )
2438 {
2439 }
2440
isBuiltin() const2441 bool CellStyleModel::isBuiltin() const
2442 {
2443 return mbBuiltin && (mnBuiltinId >= 0);
2444 }
2445
isDefaultStyle() const2446 bool CellStyleModel::isDefaultStyle() const
2447 {
2448 return mbBuiltin && (mnBuiltinId == OOX_STYLE_NORMAL);
2449 }
2450
CellStyle(const WorkbookHelper & rHelper)2451 CellStyle::CellStyle( const WorkbookHelper& rHelper ) :
2452 WorkbookHelper( rHelper ),
2453 mbCreated( false ),
2454 mpStyleSheet( nullptr )
2455 {
2456 }
2457
importCellStyle(const AttributeList & rAttribs)2458 void CellStyle::importCellStyle( const AttributeList& rAttribs )
2459 {
2460 maModel.maName = rAttribs.getXString( XML_name, OUString() );
2461 maModel.mnXfId = rAttribs.getInteger( XML_xfId, -1 );
2462 maModel.mnBuiltinId = rAttribs.getInteger( XML_builtinId, -1 );
2463 maModel.mnLevel = rAttribs.getInteger( XML_iLevel, 0 );
2464 maModel.mbBuiltin = rAttribs.hasAttribute( XML_builtinId );
2465 maModel.mbCustom = rAttribs.getBool( XML_customBuiltin, false );
2466 maModel.mbHidden = rAttribs.getBool( XML_hidden, false );
2467 }
2468
importCellStyle(SequenceInputStream & rStrm)2469 void CellStyle::importCellStyle( SequenceInputStream& rStrm )
2470 {
2471 sal_uInt16 nFlags;
2472 maModel.mnXfId = rStrm.readInt32();
2473 nFlags = rStrm.readuInt16();
2474 maModel.mnBuiltinId = rStrm.readInt8();
2475 maModel.mnLevel = rStrm.readInt8();
2476 rStrm >> maModel.maName;
2477 maModel.mbBuiltin = getFlag( nFlags, BIFF12_CELLSTYLE_BUILTIN );
2478 maModel.mbCustom = getFlag( nFlags, BIFF12_CELLSTYLE_CUSTOM );
2479 maModel.mbHidden = getFlag( nFlags, BIFF12_CELLSTYLE_HIDDEN );
2480 }
2481
createCellStyle()2482 void CellStyle::createCellStyle()
2483 {
2484
2485 // #i1624# #i1768# ignore unnamed user styles
2486 bool bDefStyle = maModel.isDefaultStyle();
2487 if( !mbCreated )
2488 {
2489 if ( bDefStyle && maFinalName.isEmpty() )
2490 maFinalName = ScResId( STR_STYLENAME_STANDARD );
2491 mbCreated = maFinalName.isEmpty();
2492 }
2493
2494 if( mbCreated || mpStyleSheet )
2495 return;
2496
2497 bool bCreatePattern = false;
2498 Xf* pXF = getStyles().getStyleXf( maModel.mnXfId ).get();
2499 ::ScDocument& rDoc = getScDocument();
2500
2501 if( bDefStyle )
2502 {
2503 // use existing "Default" style sheet
2504 mpStyleSheet = static_cast< ScStyleSheet* >( rDoc.GetStyleSheetPool()->Find(
2505 ScResId( STR_STYLENAME_STANDARD ), SfxStyleFamily::Para ) );
2506 OSL_ENSURE( mpStyleSheet, "CellStyle::createStyle - Default style not found" );
2507 bCreatePattern = true;
2508 }
2509 else
2510 {
2511 mpStyleSheet = static_cast< ScStyleSheet* >( rDoc.GetStyleSheetPool()->Find( maFinalName, SfxStyleFamily::Para ) );
2512 if( !mpStyleSheet )
2513 {
2514 mpStyleSheet = &static_cast< ScStyleSheet& >( rDoc.GetStyleSheetPool()->Make( maFinalName, SfxStyleFamily::Para, SfxStyleSearchBits::UserDefined ) );
2515 bCreatePattern = true;
2516 }
2517 }
2518
2519 // bDefStyle==true omits default pool items in CreatePattern()
2520 if( bCreatePattern && mpStyleSheet && pXF )
2521 mpStyleSheet->GetItemSet().Put( pXF->createPattern( bDefStyle ).GetItemSet() );
2522 }
2523
finalizeImport(const OUString & rFinalName)2524 void CellStyle::finalizeImport( const OUString& rFinalName )
2525 {
2526 maFinalName = rFinalName;
2527 if( !maModel.isBuiltin() || maModel.mbCustom )
2528 createCellStyle();
2529 }
2530
CellStyleBuffer(const WorkbookHelper & rHelper)2531 CellStyleBuffer::CellStyleBuffer( const WorkbookHelper& rHelper ) :
2532 WorkbookHelper( rHelper )
2533 {
2534 }
2535
importCellStyle(const AttributeList & rAttribs)2536 CellStyleRef CellStyleBuffer::importCellStyle( const AttributeList& rAttribs )
2537 {
2538 CellStyleRef xCellStyle = std::make_shared<CellStyle>( *this );
2539 xCellStyle->importCellStyle( rAttribs );
2540 insertCellStyle( xCellStyle );
2541 return xCellStyle;
2542 }
2543
importCellStyle(SequenceInputStream & rStrm)2544 CellStyleRef CellStyleBuffer::importCellStyle( SequenceInputStream& rStrm )
2545 {
2546 CellStyleRef xCellStyle = std::make_shared<CellStyle>( *this );
2547 xCellStyle->importCellStyle( rStrm );
2548 insertCellStyle( xCellStyle );
2549 return xCellStyle;
2550 }
2551
finalizeImport()2552 void CellStyleBuffer::finalizeImport()
2553 {
2554 // calculate final names of all styles
2555 typedef RefMap< OUString, CellStyle, IgnoreCaseCompare > CellStyleNameMap;
2556 CellStyleNameMap aCellStyles;
2557 CellStyleVector aConflictNameStyles;
2558
2559 /* First, reserve style names that are built-in in Calc. This causes that
2560 imported cell styles get different unused names and thus do not try to
2561 overwrite these built-in styles. */
2562 try
2563 {
2564 // unfortunately, com.sun.star.style.StyleFamily does not implement XEnumerationAccess...
2565 Reference< XIndexAccess > xStyleFamilyIA( getCellStyleFamily(), UNO_QUERY_THROW );
2566 for( sal_Int32 nIndex = 0, nCount = xStyleFamilyIA->getCount(); nIndex < nCount; ++nIndex )
2567 {
2568 Reference< XStyle > xStyle( xStyleFamilyIA->getByIndex( nIndex ), UNO_QUERY_THROW );
2569 if( !xStyle->isUserDefined() )
2570 {
2571 // create an empty entry by using ::std::map<>::operator[]
2572 aCellStyles[ xStyle->getName() ];
2573 }
2574 }
2575 }
2576 catch( Exception& )
2577 {
2578 }
2579
2580 /* Calculate names of built-in styles. Store styles with reserved names
2581 in the aConflictNameStyles list. */
2582 for( const auto& rxStyle : maBuiltinStyles )
2583 {
2584 const CellStyleModel& rModel = rxStyle->getModel();
2585 if (rModel.isDefaultStyle())
2586 continue;
2587
2588 OUString aStyleName = lclCreateStyleName( rModel );
2589 /* If a builtin style entry already exists,
2590 we just stick with the last definition and ignore
2591 the preceding ones. */
2592 aCellStyles[ aStyleName ] = rxStyle;
2593 }
2594
2595 /* Calculate names of user defined styles. Store styles with reserved
2596 names in the aConflictNameStyles list. */
2597 for( const auto& rxStyle : maUserStyles )
2598 {
2599 const CellStyleModel& rModel = rxStyle->getModel();
2600 OUString aStyleName = lclCreateStyleName( rModel );
2601 // #i1624# #i1768# ignore unnamed user styles
2602 if( aStyleName.getLength() > 0 )
2603 {
2604 if( aCellStyles.find( aStyleName ) != aCellStyles.end() )
2605 aConflictNameStyles.push_back( rxStyle );
2606 else
2607 aCellStyles[ aStyleName ] = rxStyle;
2608 }
2609 }
2610
2611 // find unused names for all styles with conflicting names
2612 // having the index counter outside the loop prevents performance problems with opening some pathological documents (tdf#62095)
2613 sal_Int32 nIndex = 0;
2614 for( const auto& rxStyle : aConflictNameStyles )
2615 {
2616 const CellStyleModel& rModel = rxStyle->getModel();
2617 OUString aStyleName = lclCreateStyleName( rModel );
2618 OUString aUnusedName;
2619 do
2620 {
2621 aUnusedName = aStyleName + OUStringChar(' ') + OUString::number( ++nIndex );
2622 }
2623 while( !aCellStyles.try_emplace( aUnusedName, rxStyle ).second );
2624 }
2625
2626 // set final names and create user-defined and modified built-in cell styles
2627 aCellStyles.forEachMemWithKey( &CellStyle::finalizeImport );
2628 }
2629
getDefaultXfId() const2630 sal_Int32 CellStyleBuffer::getDefaultXfId() const
2631 {
2632 return mxDefStyle ? mxDefStyle->getModel().mnXfId : -1;
2633 }
2634
getDefaultStyleName() const2635 OUString CellStyleBuffer::getDefaultStyleName() const
2636 {
2637 return createCellStyle( mxDefStyle );
2638 }
2639
createCellStyle(sal_Int32 nXfId) const2640 OUString CellStyleBuffer::createCellStyle( sal_Int32 nXfId ) const
2641 {
2642 return createCellStyle( maStylesByXf.get( nXfId ) );
2643 }
2644
getCellStyleSheet(sal_Int32 nXfId) const2645 ::ScStyleSheet* CellStyleBuffer::getCellStyleSheet( sal_Int32 nXfId ) const
2646 {
2647 return getCellStyleSheet( maStylesByXf.get( nXfId ) );
2648 }
2649
2650 // private --------------------------------------------------------------------
2651
insertCellStyle(CellStyleRef const & xCellStyle)2652 void CellStyleBuffer::insertCellStyle( CellStyleRef const & xCellStyle )
2653 {
2654 const CellStyleModel& rModel = xCellStyle->getModel();
2655 if( rModel.mnXfId < 0 )
2656 return;
2657
2658 // insert into the built-in map or user defined map
2659 (rModel.isBuiltin() ? maBuiltinStyles : maUserStyles).push_back( xCellStyle );
2660
2661 // insert into the XF identifier map
2662 OSL_ENSURE( maStylesByXf.count( rModel.mnXfId ) == 0, "CellStyleBuffer::insertCellStyle - multiple styles with equal XF identifier" );
2663 maStylesByXf[ rModel.mnXfId ] = xCellStyle;
2664
2665 // remember default cell style
2666 if( rModel.isDefaultStyle() )
2667 mxDefStyle = xCellStyle;
2668 }
2669
getCellStyleSheet(const CellStyleRef & rxCellStyle)2670 ::ScStyleSheet* CellStyleBuffer::getCellStyleSheet( const CellStyleRef& rxCellStyle )
2671 {
2672 ::ScStyleSheet* pStyleSheet = nullptr;
2673 if ( rxCellStyle )
2674 pStyleSheet = rxCellStyle->getStyleSheet();
2675 return pStyleSheet;
2676 }
2677
createCellStyle(const CellStyleRef & rxCellStyle)2678 OUString CellStyleBuffer::createCellStyle( const CellStyleRef& rxCellStyle )
2679 {
2680 if( rxCellStyle )
2681 {
2682 rxCellStyle->createCellStyle();
2683 const OUString& rStyleName = rxCellStyle->getFinalStyleName();
2684 if( !rStyleName.isEmpty() )
2685 return rStyleName;
2686 }
2687 // on error: fallback to default style
2688 return lclGetBuiltinStyleName( OOX_STYLE_NORMAL, u"" );
2689 }
2690
AutoFormatModel()2691 AutoFormatModel::AutoFormatModel() :
2692 mnAutoFormatId( 0 ),
2693 mbApplyNumFmt( false ),
2694 mbApplyFont( false ),
2695 mbApplyAlignment( false ),
2696 mbApplyBorder( false ),
2697 mbApplyFill( false ),
2698 mbApplyProtection( false )
2699 {
2700 }
2701
StylesBuffer(const WorkbookHelper & rHelper)2702 StylesBuffer::StylesBuffer( const WorkbookHelper& rHelper ) :
2703 WorkbookHelper( rHelper ),
2704 maPalette( rHelper ),
2705 maNumFmts( rHelper ),
2706 maCellStyles( rHelper )
2707 {
2708 }
2709
createFont()2710 FontRef StylesBuffer::createFont()
2711 {
2712 FontRef xFont = std::make_shared<Font>( *this, false );
2713 maFonts.push_back( xFont );
2714 return xFont;
2715 }
2716
createNumFmt(sal_Int32 nNumFmtId,const OUString & rFmtCode)2717 NumberFormatRef StylesBuffer::createNumFmt( sal_Int32 nNumFmtId, const OUString& rFmtCode )
2718 {
2719 return maNumFmts.createNumFmt( nNumFmtId, rFmtCode );
2720 }
2721
nextFreeNumFmtId()2722 sal_Int32 StylesBuffer::nextFreeNumFmtId()
2723 {
2724 return maNumFmts.nextFreeId();
2725 }
2726
createBorder()2727 BorderRef StylesBuffer::createBorder()
2728 {
2729 BorderRef xBorder = std::make_shared<Border>( *this, false );
2730 maBorders.push_back( xBorder );
2731 return xBorder;
2732 }
2733
createFill()2734 FillRef StylesBuffer::createFill()
2735 {
2736 FillRef xFill = std::make_shared<Fill>( *this, false );
2737 maFills.push_back( xFill );
2738 return xFill;
2739 }
2740
createCellXf()2741 XfRef StylesBuffer::createCellXf()
2742 {
2743 XfRef xXf = std::make_shared<Xf>( *this );
2744 maCellXfs.push_back( xXf );
2745 return xXf;
2746 }
2747
createStyleXf()2748 XfRef StylesBuffer::createStyleXf()
2749 {
2750 XfRef xXf = std::make_shared<Xf>( *this );
2751 maStyleXfs.push_back( xXf );
2752 return xXf;
2753 }
2754
createDxf()2755 DxfRef StylesBuffer::createDxf()
2756 {
2757 DxfRef xDxf = std::make_shared<Dxf>( *this );
2758 maDxfs.push_back( xDxf );
2759 return xDxf;
2760 }
2761
createExtDxf()2762 DxfRef StylesBuffer::createExtDxf()
2763 {
2764 DxfRef xDxf = std::make_shared<Dxf>( *this );
2765 maExtDxfs.push_back( xDxf );
2766 return xDxf;
2767 }
2768
importPaletteColor(const AttributeList & rAttribs)2769 void StylesBuffer::importPaletteColor( const AttributeList& rAttribs )
2770 {
2771 maPalette.importPaletteColor( rAttribs );
2772 }
2773
importNumFmt(const AttributeList & rAttribs)2774 NumberFormatRef StylesBuffer::importNumFmt( const AttributeList& rAttribs )
2775 {
2776 return maNumFmts.importNumFmt( rAttribs );
2777 }
2778
importCellStyle(const AttributeList & rAttribs)2779 CellStyleRef StylesBuffer::importCellStyle( const AttributeList& rAttribs )
2780 {
2781 return maCellStyles.importCellStyle( rAttribs );
2782 }
2783
importPaletteColor(SequenceInputStream & rStrm)2784 void StylesBuffer::importPaletteColor( SequenceInputStream& rStrm )
2785 {
2786 maPalette.importPaletteColor( rStrm );
2787 }
2788
importNumFmt(SequenceInputStream & rStrm)2789 void StylesBuffer::importNumFmt( SequenceInputStream& rStrm )
2790 {
2791 maNumFmts.importNumFmt( rStrm );
2792 }
2793
importCellStyle(SequenceInputStream & rStrm)2794 void StylesBuffer::importCellStyle( SequenceInputStream& rStrm )
2795 {
2796 maCellStyles.importCellStyle( rStrm );
2797 }
2798
finalizeImport()2799 void StylesBuffer::finalizeImport()
2800 {
2801 // fonts first, are needed to finalize unit converter and XFs below
2802 maFonts.forEachMem( &Font::finalizeImport );
2803 // finalize unit coefficients after default font is known
2804 getUnitConverter().finalizeImport();
2805 // number formats
2806 maNumFmts.finalizeImport();
2807 // borders and fills
2808 // is there a document wide RTL setting that we
2809 // would/could need to pass to finalizeImport here ?
2810 maBorders.forEachMem( &Border::finalizeImport, false );
2811 maFills.forEachMem( &Fill::finalizeImport );
2812 // style XFs and cell XFs
2813 maStyleXfs.forEachMem( &Xf::finalizeImport );
2814 maCellXfs.forEachMem( &Xf::finalizeImport );
2815 // built-in and user defined cell styles
2816 maCellStyles.finalizeImport();
2817 // differential formatting (for conditional formatting)
2818 maDxfs.forEachMem( &Dxf::finalizeImport );
2819 }
2820
getPaletteColor(sal_Int32 nPaletteIdx) const2821 ::Color StylesBuffer::getPaletteColor( sal_Int32 nPaletteIdx ) const
2822 {
2823 return maPalette.getColor( nPaletteIdx );
2824 }
2825
getFont(sal_Int32 nFontId) const2826 FontRef StylesBuffer::getFont( sal_Int32 nFontId ) const
2827 {
2828 return maFonts.get( nFontId );
2829 }
2830
getBorder(sal_Int32 nBorderId) const2831 BorderRef StylesBuffer::getBorder( sal_Int32 nBorderId ) const
2832 {
2833 return maBorders.get( nBorderId );
2834 }
2835
getCellXf(sal_Int32 nXfId) const2836 XfRef StylesBuffer::getCellXf( sal_Int32 nXfId ) const
2837 {
2838 return maCellXfs.get( nXfId );
2839 }
2840
getStyleXf(sal_Int32 nXfId) const2841 XfRef StylesBuffer::getStyleXf( sal_Int32 nXfId ) const
2842 {
2843 return maStyleXfs.get( nXfId );
2844 }
2845
getFontFromCellXf(sal_Int32 nXfId) const2846 FontRef StylesBuffer::getFontFromCellXf( sal_Int32 nXfId ) const
2847 {
2848 FontRef xFont;
2849 if( const Xf* pXf = getCellXf( nXfId ).get() )
2850 xFont = pXf->getFont();
2851 return xFont;
2852 }
2853
getDefaultFont() const2854 FontRef StylesBuffer::getDefaultFont() const
2855 {
2856 FontRef xDefFont;
2857 if( const Xf* pXf = getStyleXf( maCellStyles.getDefaultXfId() ).get() )
2858 xDefFont = pXf->getFont();
2859 // no font from styles - try first loaded font (e.g. BIFF2)
2860 if( !xDefFont )
2861 xDefFont = maFonts.get( 0 );
2862 OSL_ENSURE( xDefFont, "StylesBuffer::getDefaultFont - no default font found" );
2863 return xDefFont;
2864 }
2865
getDefaultFontModel() const2866 const FontModel& StylesBuffer::getDefaultFontModel() const
2867 {
2868 FontRef xDefFont = getDefaultFont();
2869 return xDefFont ? xDefFont->getModel() : getTheme().getDefaultFontModel();
2870 }
2871
equalBorders(sal_Int32 nBorderId1,sal_Int32 nBorderId2)2872 bool StylesBuffer::equalBorders( sal_Int32 nBorderId1, sal_Int32 nBorderId2 )
2873 {
2874 // in OOXML, borders are assumed to be unique
2875 return nBorderId1 == nBorderId2;
2876 }
2877
equalFills(sal_Int32 nFillId1,sal_Int32 nFillId2)2878 bool StylesBuffer::equalFills( sal_Int32 nFillId1, sal_Int32 nFillId2 )
2879 {
2880 // in OOXML, fills are assumed to be unique
2881 return nFillId1 == nFillId2;
2882 }
2883
getDefaultStyleName() const2884 OUString StylesBuffer::getDefaultStyleName() const
2885 {
2886 return maCellStyles.getDefaultStyleName();
2887 }
2888
createCellStyle(sal_Int32 nXfId) const2889 OUString StylesBuffer::createCellStyle( sal_Int32 nXfId ) const
2890 {
2891 return maCellStyles.createCellStyle( nXfId );
2892 }
2893
getCellStyleSheet(sal_Int32 nXfId) const2894 ::ScStyleSheet* StylesBuffer::getCellStyleSheet( sal_Int32 nXfId ) const
2895 {
2896 return maCellStyles.getCellStyleSheet( nXfId );
2897 }
2898
createDxfStyle(sal_Int32 nDxfId) const2899 OUString StylesBuffer::createDxfStyle( sal_Int32 nDxfId ) const
2900 {
2901 OUString& rStyleName = maDxfStyles[ nDxfId ];
2902 if (!rStyleName.isEmpty())
2903 return rStyleName;
2904
2905 if (Dxf* pDxf = maDxfs.get(nDxfId).get())
2906 {
2907 // FIXME: How can we know whether this dxf is for conditional formatting,
2908 // not for color filter? Currently this style is created for each dxf
2909 // (which might only be used by color filter)
2910 rStyleName = "ConditionalStyle_" + OUString::number(nDxfId + 1);
2911
2912 // Create a cell style. This may overwrite an existing style if
2913 // one with the same name exists.
2914 ScStyleSheet& rStyleSheet = ScfTools::MakeCellStyleSheet(
2915 *getScDocument().GetStyleSheetPool(), rStyleName, true);
2916
2917 rStyleSheet.ResetParent();
2918 SfxItemSet& rStyleItemSet =
2919 rStyleSheet.GetItemSet();
2920
2921 pDxf->fillToItemSet(rStyleItemSet);
2922
2923 }
2924
2925 // on error: fallback to default style
2926 if (rStyleName.isEmpty())
2927 rStyleName = maCellStyles.getDefaultStyleName();
2928
2929 return rStyleName;
2930 }
2931
createExtDxfStyle(sal_Int32 nDxfId) const2932 OUString StylesBuffer::createExtDxfStyle( sal_Int32 nDxfId ) const
2933 {
2934 OUString rStyleName;
2935
2936 if (Dxf* pDxf = maExtDxfs.get(nDxfId).get())
2937 {
2938 rStyleName = "ExtConditionalStyle_" + OUString::number(nDxfId + 1);
2939
2940 // Create a cell style. This may overwrite an existing style if
2941 // one with the same name exists.
2942 ScStyleSheet& rStyleSheet = ScfTools::MakeCellStyleSheet(
2943 *getScDocument().GetStyleSheetPool(), rStyleName, true);
2944
2945 rStyleSheet.ResetParent();
2946 SfxItemSet& rStyleItemSet =
2947 rStyleSheet.GetItemSet();
2948
2949 pDxf->fillToItemSet(rStyleItemSet);
2950 }
2951
2952 // on error: fallback to default style
2953 if (rStyleName.isEmpty())
2954 rStyleName = maCellStyles.getDefaultStyleName();
2955
2956 return rStyleName;
2957 }
2958
writeFontToItemSet(SfxItemSet & rItemSet,sal_Int32 nFontId,bool bSkipPoolDefs) const2959 void StylesBuffer::writeFontToItemSet( SfxItemSet& rItemSet, sal_Int32 nFontId, bool bSkipPoolDefs ) const
2960 {
2961 if( Font* pFont = maFonts.get( nFontId ).get() )
2962 pFont->fillToItemSet( rItemSet, false, bSkipPoolDefs );
2963 }
2964
writeNumFmtToItemSet(SfxItemSet & rItemSet,sal_uInt32 nNumFmtId,bool bSkipPoolDefs) const2965 sal_uInt32 StylesBuffer::writeNumFmtToItemSet( SfxItemSet& rItemSet, sal_uInt32 nNumFmtId, bool bSkipPoolDefs ) const
2966 {
2967 return maNumFmts.fillToItemSet( rItemSet, nNumFmtId, bSkipPoolDefs );
2968 }
2969
writeBorderToItemSet(SfxItemSet & rItemSet,sal_Int32 nBorderId,bool bSkipPoolDefs) const2970 void StylesBuffer::writeBorderToItemSet( SfxItemSet& rItemSet, sal_Int32 nBorderId, bool bSkipPoolDefs ) const
2971 {
2972 if( Border* pBorder = maBorders.get( nBorderId ).get() )
2973 pBorder->fillToItemSet( rItemSet, bSkipPoolDefs );
2974 }
2975
writeFillToItemSet(SfxItemSet & rItemSet,sal_Int32 nFillId,bool bSkipPoolDefs) const2976 void StylesBuffer::writeFillToItemSet( SfxItemSet& rItemSet, sal_Int32 nFillId, bool bSkipPoolDefs ) const
2977 {
2978 if( Fill* pFill = maFills.get( nFillId ).get() )
2979 pFill->fillToItemSet( rItemSet, bSkipPoolDefs );
2980 }
2981
operator ==(const XfModel & rXfModel1,const XfModel & rXfModel2)2982 bool operator==( const XfModel& rXfModel1, const XfModel& rXfModel2 )
2983 {
2984 return ( rXfModel1.mbCellXf == rXfModel2.mbCellXf &&
2985 rXfModel1.mnStyleXfId == rXfModel2.mnStyleXfId &&
2986 rXfModel1.mbFontUsed == rXfModel2.mbFontUsed &&
2987 rXfModel1.mnFontId == rXfModel2.mnFontId &&
2988 rXfModel1.mbNumFmtUsed == rXfModel2.mbNumFmtUsed &&
2989 rXfModel1.mnNumFmtId == rXfModel2.mnNumFmtId &&
2990 rXfModel1.mbAlignUsed == rXfModel2.mbAlignUsed &&
2991 rXfModel1.mbBorderUsed == rXfModel2.mbBorderUsed &&
2992 rXfModel1.mnBorderId == rXfModel2.mnBorderId &&
2993 rXfModel1.mbAreaUsed == rXfModel2.mbAreaUsed &&
2994 rXfModel1.mnFillId == rXfModel2.mnFillId &&
2995 rXfModel1.mbProtUsed == rXfModel2.mbProtUsed );
2996 }
2997
operator ==(const Xf & rXf1,const Xf & rXf2)2998 bool operator==( const Xf& rXf1, const Xf& rXf2 )
2999 {
3000 if ( rXf1.maModel == rXf2.maModel )
3001 {
3002 if ( rXf1.maModel.mbAlignUsed )
3003 {
3004 if ( !( rXf1.maAlignment.getApiData() == rXf2.maAlignment.getApiData() ) )
3005 return false;
3006 }
3007 if ( rXf1.maModel.mbProtUsed )
3008 {
3009 if ( !( rXf1.maProtection.getApiData() == rXf2.maProtection.getApiData() ) )
3010 return false;
3011 }
3012 return true;
3013 }
3014 return false;
3015 }
3016
writeCellXfToDoc(ScDocumentImport & rDoc,const ScRange & rRange,sal_Int32 nXfId) const3017 void StylesBuffer::writeCellXfToDoc(
3018 ScDocumentImport& rDoc, const ScRange& rRange, sal_Int32 nXfId ) const
3019 {
3020 Xf* pXf = maCellXfs.get(nXfId).get();
3021 if (!pXf)
3022 return;
3023
3024 pXf->writeToDoc(rDoc, rRange);
3025 }
3026
3027 } // namespace oox
3028
3029 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
3030