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