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