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 <drawingml/chart/objectformatter.hxx>
21 
22 #include <com/sun/star/chart2/XChartDocument.hpp>
23 #include <com/sun/star/lang/XMultiServiceFactory.hpp>
24 #include <com/sun/star/util/XNumberFormatsSupplier.hpp>
25 #include <com/sun/star/util/XNumberFormatTypes.hpp>
26 #include <osl/thread.h>
27 #include <osl/diagnose.h>
28 #include <rtl/strbuf.hxx>
29 #include <oox/core/xmlfilterbase.hxx>
30 #include <drawingml/fillproperties.hxx>
31 #include <drawingml/lineproperties.hxx>
32 #include <oox/drawingml/shapepropertymap.hxx>
33 #include <drawingml/textbody.hxx>
34 #include <drawingml/textparagraph.hxx>
35 #include <oox/drawingml/theme.hxx>
36 #include <drawingml/chart/chartspacemodel.hxx>
37 #include <oox/helper/modelobjecthelper.hxx>
38 #include <oox/helper/graphichelper.hxx>
39 #include <oox/token/properties.hxx>
40 #include <oox/token/tokens.hxx>
41 
42 namespace oox::drawingml::chart {
43 
44 using namespace ::com::sun::star::chart2;
45 using namespace ::com::sun::star::graphic;
46 using namespace ::com::sun::star::lang;
47 using namespace ::com::sun::star::uno;
48 using namespace ::com::sun::star::util;
49 
50 using ::oox::core::XmlFilterBase;
51 
52 namespace {
53 
54 struct AutoFormatPatternEntry
55 {
56     sal_Int32           mnColorToken;       /// Theme color token.
57     sal_Int32           mnModToken;         /// Color modification token.
58     sal_Int32           mnModValue;         /// Color modification value.
59 };
60 
61 #define AUTOFORMAT_PATTERN_COLOR( color_token ) \
62     { color_token, XML_TOKEN_INVALID, 0 }
63 
64 #define AUTOFORMAT_PATTERN_COLORMOD( color_token, mod_token, mod_value ) \
65     { color_token, mod_token, mod_value }
66 
67 #define AUTOFORMAT_PATTERN_END() \
68     AUTOFORMAT_PATTERN_COLOR( XML_TOKEN_INVALID )
69 
70 const AutoFormatPatternEntry spAutoFormatPattern1[] =
71 {
72     AUTOFORMAT_PATTERN_COLORMOD( XML_dk1, XML_tint, 88500 ),
73     AUTOFORMAT_PATTERN_COLORMOD( XML_dk1, XML_tint, 55000 ),
74     AUTOFORMAT_PATTERN_COLORMOD( XML_dk1, XML_tint, 78000 ),
75     AUTOFORMAT_PATTERN_COLORMOD( XML_dk1, XML_tint, 92500 ),
76     AUTOFORMAT_PATTERN_COLORMOD( XML_dk1, XML_tint, 70000 ),
77     AUTOFORMAT_PATTERN_COLORMOD( XML_dk1, XML_tint, 30000 ),
78     AUTOFORMAT_PATTERN_END()
79 };
80 
81 const AutoFormatPatternEntry spAutoFormatPattern2[] =
82 {
83     AUTOFORMAT_PATTERN_COLOR( XML_accent1 ),
84     AUTOFORMAT_PATTERN_COLOR( XML_accent2 ),
85     AUTOFORMAT_PATTERN_COLOR( XML_accent3 ),
86     AUTOFORMAT_PATTERN_COLOR( XML_accent4 ),
87     AUTOFORMAT_PATTERN_COLOR( XML_accent5 ),
88     AUTOFORMAT_PATTERN_COLOR( XML_accent6 ),
89     AUTOFORMAT_PATTERN_END()
90 };
91 
92 const AutoFormatPatternEntry spAutoFormatPattern3[] =
93 {
94     AUTOFORMAT_PATTERN_COLORMOD( XML_accent1, XML_shade, 50000 ),
95     AUTOFORMAT_PATTERN_COLORMOD( XML_accent2, XML_shade, 50000 ),
96     AUTOFORMAT_PATTERN_COLORMOD( XML_accent3, XML_shade, 50000 ),
97     AUTOFORMAT_PATTERN_COLORMOD( XML_accent4, XML_shade, 50000 ),
98     AUTOFORMAT_PATTERN_COLORMOD( XML_accent5, XML_shade, 50000 ),
99     AUTOFORMAT_PATTERN_COLORMOD( XML_accent6, XML_shade, 50000 ),
100     AUTOFORMAT_PATTERN_END()
101 };
102 
103 const AutoFormatPatternEntry spAutoFormatPattern4[] =
104 {
105     AUTOFORMAT_PATTERN_COLORMOD( XML_dk1, XML_tint,  5000 ),
106     AUTOFORMAT_PATTERN_COLORMOD( XML_dk1, XML_tint, 55000 ),
107     AUTOFORMAT_PATTERN_COLORMOD( XML_dk1, XML_tint, 78000 ),
108     AUTOFORMAT_PATTERN_COLORMOD( XML_dk1, XML_tint, 15000 ),
109     AUTOFORMAT_PATTERN_COLORMOD( XML_dk1, XML_tint, 70000 ),
110     AUTOFORMAT_PATTERN_COLORMOD( XML_dk1, XML_tint, 30000 ),
111     AUTOFORMAT_PATTERN_END()
112 };
113 
114 #undef AUTOFORMAT_PATTERN_COLOR
115 #undef AUTOFORMAT_PATTERN_COLORMOD
116 #undef AUTOFORMAT_PATTERN_END
117 
118 struct AutoFormatEntry
119 {
120     sal_Int32           mnFirstStyleIdx;    /// First chart style index.
121     sal_Int32           mnLastStyleIdx;     /// Last chart style index.
122     sal_Int32           mnThemedIdx;        /// Themed style index.
123     sal_Int32           mnColorToken;       /// Theme color token.
124     sal_Int32           mnModToken;         /// Color modification token.
125     sal_Int32           mnModValue;         /// Color modification value.
126     sal_Int32           mnRelLineWidth;     /// Relative line width (percent).
127     const AutoFormatPatternEntry* mpPattern;/// Color cycling pattern for data series.
128     bool                mbFadedColor;       /// True = Faded color for data series.
129 };
130 
131 #define AUTOFORMAT_COLOR( first, last, themed_style, color_token ) \
132     { first, last, themed_style, color_token, XML_TOKEN_INVALID, 0, 100, nullptr, false }
133 
134 #define AUTOFORMAT_COLORMOD( first, last, themed_style, color_token, mod_token, mod_value ) \
135     { first, last, themed_style, color_token, mod_token, mod_value, 100, nullptr, false }
136 
137 #define AUTOFORMAT_ACCENTSMOD( first, themed_style, mod_token, mod_value ) \
138     AUTOFORMAT_COLORMOD( first,     first,     themed_style, XML_accent1, mod_token, mod_value ), \
139     AUTOFORMAT_COLORMOD( first + 1, first + 1, themed_style, XML_accent2, mod_token, mod_value ), \
140     AUTOFORMAT_COLORMOD( first + 2, first + 2, themed_style, XML_accent3, mod_token, mod_value ), \
141     AUTOFORMAT_COLORMOD( first + 3, first + 3, themed_style, XML_accent4, mod_token, mod_value ), \
142     AUTOFORMAT_COLORMOD( first + 4, first + 4, themed_style, XML_accent5, mod_token, mod_value ), \
143     AUTOFORMAT_COLORMOD( first + 5, first + 5, themed_style, XML_accent6, mod_token, mod_value )
144 
145 #define AUTOFORMAT_PATTERN( first, last, themed_style, line_width, pattern ) \
146     { first, last, themed_style, XML_TOKEN_INVALID, XML_TOKEN_INVALID, 0, line_width, pattern, false }
147 
148 #define AUTOFORMAT_FADED( first, last, themed_style, color_token, line_width ) \
149     { first, last, themed_style, color_token, XML_TOKEN_INVALID, 0, line_width, nullptr, true }
150 
151 #define AUTOFORMAT_FADEDACCENTS( first, themed_style, line_width ) \
152     AUTOFORMAT_FADED( first,     first,     themed_style, XML_accent1, line_width ), \
153     AUTOFORMAT_FADED( first + 1, first + 1, themed_style, XML_accent2, line_width ), \
154     AUTOFORMAT_FADED( first + 2, first + 2, themed_style, XML_accent3, line_width ), \
155     AUTOFORMAT_FADED( first + 3, first + 3, themed_style, XML_accent4, line_width ), \
156     AUTOFORMAT_FADED( first + 4, first + 4, themed_style, XML_accent5, line_width ), \
157     AUTOFORMAT_FADED( first + 5, first + 5, themed_style, XML_accent6, line_width )
158 
159 #define AUTOFORMAT_INVISIBLE( first, last ) \
160     AUTOFORMAT_COLOR( first, last, -1, XML_TOKEN_INVALID )
161 
162 #define AUTOFORMAT_END() \
163     AUTOFORMAT_INVISIBLE( -1, -1 )
164 
165 const AutoFormatEntry spNoFormats[] =
166 {
167     AUTOFORMAT_INVISIBLE( 1, 48 ),
168     AUTOFORMAT_END()
169 };
170 
171 const AutoFormatEntry spChartSpaceFill[] =
172 {
173     AUTOFORMAT_COLOR( 1, 32, THEMED_STYLE_SUBTLE, XML_bg1 ),
174     AUTOFORMAT_COLOR( 33, 40, THEMED_STYLE_SUBTLE, XML_lt1 ),
175     AUTOFORMAT_COLOR( 41, 48, THEMED_STYLE_SUBTLE, XML_dk1 ),
176     AUTOFORMAT_END()
177 };
178 
179 const AutoFormatEntry spDataTableLines[] =
180 {
181     AUTOFORMAT_COLORMOD(  1, 32, THEMED_STYLE_SUBTLE, XML_tx1, XML_tint, 75000 ),
182     AUTOFORMAT_COLORMOD( 33, 40, THEMED_STYLE_SUBTLE, XML_dk1, XML_tint, 75000 ),
183     // 41...48: no line, same as Chart2
184     AUTOFORMAT_END()
185 };
186 
187 const AutoFormatEntry spPlotArea2dFills[] =
188 {
189     AUTOFORMAT_COLOR(       1, 32, THEMED_STYLE_SUBTLE, XML_bg1 ),
190     AUTOFORMAT_COLORMOD(   33, 34, THEMED_STYLE_SUBTLE, XML_dk1, XML_tint, 20000 ),
191     AUTOFORMAT_ACCENTSMOD( 35,     THEMED_STYLE_SUBTLE,          XML_tint, 20000 ), // tint not documented!?
192     AUTOFORMAT_COLORMOD(   41, 48, THEMED_STYLE_SUBTLE, XML_dk1, XML_tint, 95000 ),
193     AUTOFORMAT_END()
194 };
195 
196 const AutoFormatEntry spWallFloorLines[] =
197 {
198     AUTOFORMAT_COLORMOD(  1, 32, THEMED_STYLE_SUBTLE, XML_tx1, XML_tint, 75000 ),
199     AUTOFORMAT_COLORMOD( 33, 40, THEMED_STYLE_SUBTLE, XML_dk1, XML_tint, 75000 ),
200     // 41...48: no line, same as Chart2
201     AUTOFORMAT_END()
202 };
203 
204 const AutoFormatEntry spWallFloorFills[] =
205 {
206     AUTOFORMAT_INVISIBLE(   1, 32 ),
207     AUTOFORMAT_COLORMOD(   33, 34, THEMED_STYLE_SUBTLE, XML_dk1, XML_tint, 20000 ),
208     AUTOFORMAT_ACCENTSMOD( 35,     THEMED_STYLE_SUBTLE,          XML_tint, 20000 ), // tint not documented!?
209     AUTOFORMAT_COLORMOD(   41, 48, THEMED_STYLE_SUBTLE, XML_dk1, XML_tint, 95000 ),
210     AUTOFORMAT_END()
211 };
212 
213 const AutoFormatEntry spAxisLines[] =
214 {
215     AUTOFORMAT_COLORMOD(  1, 32, THEMED_STYLE_SUBTLE, XML_tx1, XML_tint, 75000 ),   // tint not documented!?
216     AUTOFORMAT_COLORMOD( 33, 48, THEMED_STYLE_SUBTLE, XML_dk1, XML_tint, 75000 ),   // tint not documented!?
217     AUTOFORMAT_END()
218 };
219 
220 const AutoFormatEntry spMajorGridLines[] =
221 {
222     AUTOFORMAT_COLORMOD(  1, 32, THEMED_STYLE_SUBTLE, XML_tx1, XML_tint, 75000 ),   // tint not documented!?
223     AUTOFORMAT_COLORMOD( 33, 48, THEMED_STYLE_SUBTLE, XML_dk1, XML_tint, 75000 ),   // tint not documented!?
224     AUTOFORMAT_END()
225 };
226 
227 const AutoFormatEntry spMinorGridLines[] =
228 {
229     AUTOFORMAT_COLORMOD(  1, 40, THEMED_STYLE_SUBTLE, XML_tx1, XML_tint, 50000 ),
230     AUTOFORMAT_COLORMOD( 41, 48, THEMED_STYLE_SUBTLE, XML_tx1, XML_tint, 90000 ),
231     AUTOFORMAT_END()
232 };
233 
234 const AutoFormatEntry spOtherLines[] =
235 {
236     AUTOFORMAT_COLOR(     1, 32, THEMED_STYLE_SUBTLE, XML_tx1 ),
237     AUTOFORMAT_COLOR(    33, 34, THEMED_STYLE_SUBTLE, XML_dk1 ),
238     AUTOFORMAT_COLORMOD( 35, 40, THEMED_STYLE_SUBTLE, XML_dk1, XML_shade, 25000 ),
239     AUTOFORMAT_COLOR(    41, 48, THEMED_STYLE_SUBTLE, XML_lt1 ),
240     AUTOFORMAT_END()
241 };
242 
243 const AutoFormatEntry spLinearSeriesLines[] =
244 {
245     AUTOFORMAT_PATTERN(       1,  1, THEMED_STYLE_SUBTLE, 300, spAutoFormatPattern1 ),
246     AUTOFORMAT_PATTERN(       2,  2, THEMED_STYLE_SUBTLE, 300, spAutoFormatPattern2 ),
247     AUTOFORMAT_FADEDACCENTS(  3,     THEMED_STYLE_SUBTLE, 300 ),
248     AUTOFORMAT_PATTERN(       9,  9, THEMED_STYLE_SUBTLE, 500, spAutoFormatPattern1 ),
249     AUTOFORMAT_PATTERN(      10, 10, THEMED_STYLE_SUBTLE, 500, spAutoFormatPattern2 ),
250     AUTOFORMAT_FADEDACCENTS( 11,     THEMED_STYLE_SUBTLE, 500 ),
251     AUTOFORMAT_PATTERN(      17, 17, THEMED_STYLE_SUBTLE, 500, spAutoFormatPattern1 ),
252     AUTOFORMAT_PATTERN(      18, 18, THEMED_STYLE_SUBTLE, 500, spAutoFormatPattern2 ),
253     AUTOFORMAT_FADEDACCENTS( 19,     THEMED_STYLE_SUBTLE, 500 ),
254     AUTOFORMAT_PATTERN(      25, 25, THEMED_STYLE_SUBTLE, 700, spAutoFormatPattern1 ),
255     AUTOFORMAT_PATTERN(      26, 26, THEMED_STYLE_SUBTLE, 700, spAutoFormatPattern2 ),
256     AUTOFORMAT_FADEDACCENTS( 27,     THEMED_STYLE_SUBTLE, 700 ),
257     AUTOFORMAT_PATTERN(      33, 33, THEMED_STYLE_SUBTLE, 500, spAutoFormatPattern1 ),
258     AUTOFORMAT_PATTERN(      34, 34, THEMED_STYLE_SUBTLE, 500, spAutoFormatPattern2 ),
259     AUTOFORMAT_FADEDACCENTS( 35,     THEMED_STYLE_SUBTLE, 500 ),
260     AUTOFORMAT_PATTERN(      41, 42, THEMED_STYLE_SUBTLE, 500, spAutoFormatPattern4 ),
261     AUTOFORMAT_PATTERN(      42, 42, THEMED_STYLE_SUBTLE, 500, spAutoFormatPattern2 ),
262     AUTOFORMAT_FADEDACCENTS( 43,     THEMED_STYLE_SUBTLE, 500 ),
263     AUTOFORMAT_END()
264 };
265 
266 const AutoFormatEntry spFilledSeriesLines[] =
267 {
268     AUTOFORMAT_INVISIBLE(   1,  8 ),
269     AUTOFORMAT_COLOR(       9, 16, THEMED_STYLE_SUBTLE, XML_lt1 ),
270     AUTOFORMAT_INVISIBLE(  17, 32 ),
271     AUTOFORMAT_COLORMOD(   33, 33, THEMED_STYLE_SUBTLE, XML_dk1, XML_shade, 50000 ),
272     AUTOFORMAT_PATTERN(    34, 34, THEMED_STYLE_SUBTLE, 100, spAutoFormatPattern3 ),
273     AUTOFORMAT_ACCENTSMOD( 35,     THEMED_STYLE_SUBTLE,          XML_shade, 50000 ),
274     AUTOFORMAT_INVISIBLE(  41, 48 ),
275     AUTOFORMAT_END()
276 };
277 
278 const AutoFormatEntry spFilledSeries2dFills[] =
279 {
280     AUTOFORMAT_PATTERN(       1,  1, THEMED_STYLE_SUBTLE,  100, spAutoFormatPattern1 ),
281     AUTOFORMAT_PATTERN(       2,  2, THEMED_STYLE_SUBTLE,  100, spAutoFormatPattern2 ),
282     AUTOFORMAT_FADEDACCENTS(  3,     THEMED_STYLE_SUBTLE,  100 ),
283     AUTOFORMAT_PATTERN(       9,  9, THEMED_STYLE_SUBTLE,  100, spAutoFormatPattern1 ),
284     AUTOFORMAT_PATTERN(      10, 10, THEMED_STYLE_SUBTLE,  100, spAutoFormatPattern2 ),
285     AUTOFORMAT_FADEDACCENTS( 11,     THEMED_STYLE_SUBTLE,  100 ),
286     AUTOFORMAT_PATTERN(      17, 17, THEMED_STYLE_INTENSE, 100, spAutoFormatPattern1 ),
287     AUTOFORMAT_PATTERN(      18, 18, THEMED_STYLE_INTENSE, 100, spAutoFormatPattern2 ),
288     AUTOFORMAT_FADEDACCENTS( 19,     THEMED_STYLE_INTENSE, 100 ),
289     AUTOFORMAT_PATTERN(      25, 25, THEMED_STYLE_INTENSE, 100, spAutoFormatPattern1 ),
290     AUTOFORMAT_PATTERN(      26, 26, THEMED_STYLE_INTENSE, 100, spAutoFormatPattern2 ),
291     AUTOFORMAT_FADEDACCENTS( 27,     THEMED_STYLE_INTENSE, 100 ),
292     AUTOFORMAT_PATTERN(      33, 33, THEMED_STYLE_SUBTLE,  100, spAutoFormatPattern1 ),
293     AUTOFORMAT_PATTERN(      34, 34, THEMED_STYLE_SUBTLE,  100, spAutoFormatPattern2 ),
294     AUTOFORMAT_FADEDACCENTS( 35,     THEMED_STYLE_SUBTLE,  100 ),
295     AUTOFORMAT_PATTERN(      41, 42, THEMED_STYLE_INTENSE, 100, spAutoFormatPattern4 ),
296     AUTOFORMAT_PATTERN(      42, 42, THEMED_STYLE_INTENSE, 100, spAutoFormatPattern2 ),
297     AUTOFORMAT_FADEDACCENTS( 43,     THEMED_STYLE_INTENSE, 100 ),
298     AUTOFORMAT_END()
299 };
300 
301 const AutoFormatEntry spFilledSeries3dFills[] =
302 {
303     AUTOFORMAT_PATTERN(       1,  1, THEMED_STYLE_SUBTLE,  100, spAutoFormatPattern1 ),
304     AUTOFORMAT_PATTERN(       2,  2, THEMED_STYLE_SUBTLE,  100, spAutoFormatPattern2 ),
305     AUTOFORMAT_FADEDACCENTS(  3,     THEMED_STYLE_SUBTLE,  100 ),
306     AUTOFORMAT_PATTERN(       9,  9, THEMED_STYLE_SUBTLE,  100, spAutoFormatPattern1 ),
307     AUTOFORMAT_PATTERN(      10, 10, THEMED_STYLE_SUBTLE,  100, spAutoFormatPattern2 ),
308     AUTOFORMAT_FADEDACCENTS( 11,     THEMED_STYLE_SUBTLE,  100 ),
309     AUTOFORMAT_PATTERN(      17, 17, THEMED_STYLE_SUBTLE,  100, spAutoFormatPattern1 ),
310     AUTOFORMAT_PATTERN(      18, 18, THEMED_STYLE_INTENSE, 100, spAutoFormatPattern2 ),
311     AUTOFORMAT_FADEDACCENTS( 19,     THEMED_STYLE_SUBTLE,  100 ),
312     AUTOFORMAT_PATTERN(      25, 25, THEMED_STYLE_SUBTLE,  100, spAutoFormatPattern1 ),
313     AUTOFORMAT_PATTERN(      26, 26, THEMED_STYLE_INTENSE, 100, spAutoFormatPattern2 ),
314     AUTOFORMAT_FADEDACCENTS( 27,     THEMED_STYLE_SUBTLE,  100 ),
315     AUTOFORMAT_PATTERN(      33, 33, THEMED_STYLE_SUBTLE,  100, spAutoFormatPattern1 ),
316     AUTOFORMAT_PATTERN(      34, 34, THEMED_STYLE_SUBTLE,  100, spAutoFormatPattern2 ),
317     AUTOFORMAT_FADEDACCENTS( 35,     THEMED_STYLE_SUBTLE,  100 ),
318     AUTOFORMAT_PATTERN(      41, 42, THEMED_STYLE_SUBTLE,  100, spAutoFormatPattern4 ),
319     AUTOFORMAT_PATTERN(      42, 42, THEMED_STYLE_INTENSE, 100, spAutoFormatPattern2 ),
320     AUTOFORMAT_FADEDACCENTS( 43,     THEMED_STYLE_SUBTLE,  100 ),
321     AUTOFORMAT_END()
322 };
323 
324 const AutoFormatEntry spUpDownBarLines[] =
325 {
326     AUTOFORMAT_COLOR(       1, 16, THEMED_STYLE_SUBTLE, XML_tx1 ),
327     AUTOFORMAT_INVISIBLE(  17, 32 ),
328     AUTOFORMAT_COLOR(      33, 34, THEMED_STYLE_SUBTLE, XML_dk1 ),
329     AUTOFORMAT_ACCENTSMOD( 35,     THEMED_STYLE_SUBTLE, XML_shade, 25000 ),
330     AUTOFORMAT_INVISIBLE(  41, 48 ),
331     AUTOFORMAT_END()
332 };
333 
334 const AutoFormatEntry spUpBarFills[] =
335 {
336     AUTOFORMAT_COLORMOD(    1,  1, THEMED_STYLE_SUBTLE,  XML_dk1, XML_tint, 25000 ),
337     AUTOFORMAT_COLORMOD(    2,  2, THEMED_STYLE_SUBTLE,  XML_dk1, XML_tint,  5000 ),
338     AUTOFORMAT_ACCENTSMOD(  3,     THEMED_STYLE_SUBTLE,           XML_tint, 25000 ),
339     AUTOFORMAT_COLORMOD(    9,  9, THEMED_STYLE_SUBTLE,  XML_dk1, XML_tint, 25000 ),
340     AUTOFORMAT_COLORMOD(   10, 10, THEMED_STYLE_SUBTLE,  XML_dk1, XML_tint,  5000 ),
341     AUTOFORMAT_ACCENTSMOD( 11,     THEMED_STYLE_SUBTLE,           XML_tint, 25000 ),
342     AUTOFORMAT_COLORMOD(   17, 17, THEMED_STYLE_INTENSE, XML_dk1, XML_tint, 25000 ),
343     AUTOFORMAT_COLORMOD(   18, 18, THEMED_STYLE_INTENSE, XML_dk1, XML_tint,  5000 ),
344     AUTOFORMAT_ACCENTSMOD( 19,     THEMED_STYLE_INTENSE,          XML_tint, 25000 ),
345     AUTOFORMAT_COLORMOD(   25, 25, THEMED_STYLE_INTENSE, XML_dk1, XML_tint, 25000 ),
346     AUTOFORMAT_COLORMOD(   26, 26, THEMED_STYLE_INTENSE, XML_dk1, XML_tint,  5000 ),
347     AUTOFORMAT_ACCENTSMOD( 27,     THEMED_STYLE_INTENSE,          XML_tint, 25000 ),
348     AUTOFORMAT_COLOR(      33, 40, THEMED_STYLE_SUBTLE,  XML_lt1 ),
349     AUTOFORMAT_COLORMOD(   41, 41, THEMED_STYLE_INTENSE, XML_dk1, XML_tint, 25000 ),
350     AUTOFORMAT_COLOR(      42, 42, THEMED_STYLE_INTENSE, XML_lt1 ),
351     AUTOFORMAT_ACCENTSMOD( 43,     THEMED_STYLE_INTENSE,          XML_tint, 25000 ),
352     AUTOFORMAT_END()
353 };
354 
355 const AutoFormatEntry spDownBarFills[] =
356 {
357     AUTOFORMAT_COLORMOD(    1,  1, THEMED_STYLE_SUBTLE,  XML_dk1, XML_tint,  85000 ),
358     AUTOFORMAT_COLORMOD(    2,  2, THEMED_STYLE_SUBTLE,  XML_dk1, XML_tint,  95000 ),
359     AUTOFORMAT_ACCENTSMOD(  3,     THEMED_STYLE_SUBTLE,           XML_shade, 25000 ),
360     AUTOFORMAT_COLORMOD(    9,  9, THEMED_STYLE_SUBTLE,  XML_dk1, XML_tint,  85000 ),
361     AUTOFORMAT_COLORMOD(   10, 10, THEMED_STYLE_SUBTLE,  XML_dk1, XML_tint,  95000 ),
362     AUTOFORMAT_ACCENTSMOD( 11,     THEMED_STYLE_SUBTLE,           XML_shade, 25000 ),
363     AUTOFORMAT_COLORMOD(   17, 17, THEMED_STYLE_INTENSE, XML_dk1, XML_tint,  85000 ),
364     AUTOFORMAT_COLORMOD(   18, 18, THEMED_STYLE_INTENSE, XML_dk1, XML_tint,  95000 ),
365     AUTOFORMAT_ACCENTSMOD( 19,     THEMED_STYLE_INTENSE,          XML_shade, 25000 ),
366     AUTOFORMAT_COLORMOD(   25, 25, THEMED_STYLE_INTENSE, XML_dk1, XML_tint,  85000 ),
367     AUTOFORMAT_COLORMOD(   26, 26, THEMED_STYLE_INTENSE, XML_dk1, XML_tint,  95000 ),
368     AUTOFORMAT_ACCENTSMOD( 27,     THEMED_STYLE_INTENSE,          XML_shade, 25000 ),
369     AUTOFORMAT_COLORMOD(   33, 33, THEMED_STYLE_SUBTLE,  XML_dk1, XML_tint,  85000 ),
370     AUTOFORMAT_COLORMOD(   34, 34, THEMED_STYLE_SUBTLE,  XML_dk1, XML_tint,  95000 ),
371     AUTOFORMAT_ACCENTSMOD( 35,     THEMED_STYLE_SUBTLE,           XML_shade, 25000 ),
372     AUTOFORMAT_COLORMOD(   41, 41, THEMED_STYLE_INTENSE, XML_dk1, XML_tint,  85000 ),
373     AUTOFORMAT_COLOR(      42, 42, THEMED_STYLE_INTENSE, XML_dk1 ),
374     AUTOFORMAT_ACCENTSMOD( 43,     THEMED_STYLE_INTENSE,          XML_shade, 25000 ),
375     AUTOFORMAT_END()
376 };
377 
378 #undef AUTOFORMAT_COLOR
379 #undef AUTOFORMAT_COLORMOD
380 #undef AUTOFORMAT_ACCENTSMOD
381 #undef AUTOFORMAT_PATTERN
382 #undef AUTOFORMAT_FADED
383 #undef AUTOFORMAT_FADEDACCENTS
384 #undef AUTOFORMAT_INVISIBLE
385 #undef AUTOFORMAT_END
386 
lclGetAutoFormatEntry(const AutoFormatEntry * pEntries,sal_Int32 nStyle)387 const AutoFormatEntry* lclGetAutoFormatEntry( const AutoFormatEntry* pEntries, sal_Int32 nStyle )
388 {
389     for( ; pEntries && (pEntries->mnFirstStyleIdx >= 0); ++pEntries )
390         if( (pEntries->mnFirstStyleIdx <= nStyle) && (nStyle <= pEntries->mnLastStyleIdx) )
391             return pEntries;
392     return nullptr;
393 }
394 
395 struct AutoTextEntry
396 {
397     sal_Int32           mnFirstStyleIdx;    /// First chart style index.
398     sal_Int32           mnLastStyleIdx;     /// Last chart style index.
399     sal_Int32           mnThemedFont;       /// Themed font (minor/major).
400     sal_Int32           mnColorToken;       /// Theme color token.
401     sal_Int32           mnDefFontSize;      /// Default font size (1/100 points).
402     sal_Int32           mnRelFontSize;      /// Font size relative to chart global font (percent).
403     bool                mbBold;             /// True = bold font.
404 };
405 
406 #define AUTOTEXT_COLOR( first, last, themed_font, color_token, def_font_size, rel_font_size, bold ) \
407     { first, last, themed_font, color_token, def_font_size, rel_font_size, bold }
408 
409 #define AUTOTEXT_END() \
410     AUTOTEXT_COLOR( -1, -1, XML_none, XML_TOKEN_INVALID, 1000, 100, false )
411 
412 const AutoTextEntry spChartTitleTexts[] =
413 {
414     AUTOTEXT_COLOR(  1, 40, XML_minor, XML_tx1, 1800, 120, true ),
415     AUTOTEXT_COLOR( 41, 48, XML_minor, XML_lt1, 1800, 120, true ),
416     AUTOTEXT_END()
417 };
418 
419 const AutoTextEntry spAxisTitleTexts[] =
420 {
421     AUTOTEXT_COLOR(  1, 40, XML_minor, XML_tx1, 1000, 100, true ),
422     AUTOTEXT_COLOR( 41, 48, XML_minor, XML_lt1, 1000, 100, true ),
423     AUTOTEXT_END()
424 };
425 
426 const AutoTextEntry spOtherTexts[] =
427 {
428     AUTOTEXT_COLOR(  1, 40, XML_minor, XML_tx1, 1000, 100, false ),
429     AUTOTEXT_COLOR( 41, 48, XML_minor, XML_lt1, 1000, 100, false ),
430     AUTOTEXT_END()
431 };
432 
433 #undef AUTOTEXT_COLOR
434 #undef AUTOTEXT_END
435 
lclGetAutoTextEntry(const AutoTextEntry * pEntries,sal_Int32 nStyle)436 const AutoTextEntry* lclGetAutoTextEntry( const AutoTextEntry* pEntries, sal_Int32 nStyle )
437 {
438     for( ; pEntries && (pEntries->mnFirstStyleIdx >= 0); ++pEntries )
439         if( (pEntries->mnFirstStyleIdx <= nStyle) && (nStyle <= pEntries->mnLastStyleIdx) )
440             return pEntries;
441     return nullptr;
442 }
443 
444 // These PropIds arrays will be indexed into using a ShapeProperty enum
445 
446 const ShapePropertyIds spnCommonPropIds =
447 {
448     PROP_LineStyle, PROP_LineWidth, PROP_LineColor, PROP_LineTransparence, PROP_LineDashName,
449     PROP_LineCap, PROP_INVALID, PROP_INVALID, PROP_INVALID, PROP_INVALID, PROP_INVALID, PROP_INVALID, PROP_INVALID,
450     PROP_FillStyle, PROP_FillColor, PROP_FillTransparence, PROP_FillTransparenceGradientName, PROP_FillGradientName,
451     PROP_FillBitmapName, PROP_FillBitmapMode, PROP_FillBitmapSizeX, PROP_FillBitmapSizeY,
452     PROP_FillBitmapPositionOffsetX, PROP_FillBitmapPositionOffsetY, PROP_FillBitmapRectanglePoint,
453     PROP_FillHatchName, PROP_FillBackground
454 };
455 
456 const ShapePropertyIds spnLinearPropIds =
457 {
458     PROP_LineStyle, PROP_LineWidth, PROP_Color, PROP_Transparency, PROP_LineDashName,
459     PROP_LineCap, PROP_INVALID, PROP_INVALID, PROP_INVALID, PROP_INVALID, PROP_INVALID, PROP_INVALID, PROP_INVALID,
460     PROP_INVALID, PROP_INVALID, PROP_INVALID, PROP_INVALID, PROP_INVALID,
461     PROP_INVALID, PROP_INVALID, PROP_INVALID, PROP_INVALID,
462     PROP_INVALID, PROP_INVALID, PROP_INVALID,
463     PROP_INVALID, PROP_INVALID
464 };
465 
466 const ShapePropertyIds spnFilledPropIds =
467 {
468     PROP_BorderStyle,
469     PROP_BorderWidth,
470     PROP_BorderColor,
471     PROP_BorderTransparency,
472     PROP_BorderDashName,
473     PROP_LineCap,
474     PROP_INVALID,
475     PROP_INVALID,
476     PROP_INVALID,
477     PROP_INVALID,
478     PROP_INVALID,
479     PROP_INVALID,
480     PROP_INVALID,
481     PROP_FillStyle,
482     PROP_Color,
483     PROP_Transparency,
484     PROP_FillTransparenceGradientName,
485     PROP_GradientName,
486     PROP_FillBitmapName,
487     PROP_FillBitmapMode,
488     PROP_FillBitmapSizeX,
489     PROP_FillBitmapSizeY,
490     PROP_FillBitmapPositionOffsetX,
491     PROP_FillBitmapPositionOffsetY,
492     PROP_FillBitmapRectanglePoint,
493     PROP_HatchName,
494     PROP_FillBackground
495 };
496 
497 /** Property info for common chart objects, to be used in ShapePropertyMap. */
498 const ShapePropertyInfo saCommonPropInfo( spnCommonPropIds, false, true, true, true, true );
499 /** Property info for linear data series, to be used in ShapePropertyMap. */
500 const ShapePropertyInfo saLinearPropInfo( spnLinearPropIds, false, true, true, true, true );
501 /** Property info for filled data series, to be used in ShapePropertyMap. */
502 const ShapePropertyInfo saFilledPropInfo( spnFilledPropIds, false, true, true, true, true );
503 
504 /** Contains information about formatting of a specific chart object type. */
505 struct ObjectTypeFormatEntry
506 {
507     ObjectType          meObjType;          /// Object type for automatic format.
508     const ShapePropertyInfo& mrPropInfo;    /// Property info for the ShapePropertyMap class.
509     const AutoFormatEntry* mpAutoLines;     /// Automatic line formatting for all chart styles.
510     const AutoFormatEntry* mpAutoFills;     /// Automatic fill formatting for all chart styles.
511     const AutoTextEntry* mpAutoTexts;       /// Automatic text attributes for all chart styles.
512     bool                mbIsFrame;          /// True = object is a frame, false = object is a line.
ObjectTypeFormatEntryoox::drawingml::chart::__anon947c88130111::ObjectTypeFormatEntry513     ObjectTypeFormatEntry(ObjectType eObjType, const ShapePropertyInfo& rPropInfo,
514                                  const AutoFormatEntry* pAutoLines,
515                                  const AutoFormatEntry* pAutoFills,
516                                  const AutoTextEntry* pAutoTexts,
517                                  bool bIsFrame)
518         :meObjType(eObjType), mrPropInfo(rPropInfo), mpAutoLines(pAutoLines)
519         ,mpAutoFills(pAutoFills), mpAutoTexts(pAutoTexts), mbIsFrame(bIsFrame)
520     {} // prevent creation of implicit default ctor which fails in MSVC
521 };
522 
523 #define TYPEFORMAT_FRAME( obj_type, prop_type, auto_texts, auto_lines, auto_fills ) \
524     { obj_type, prop_type, auto_lines, auto_fills, auto_texts, true }
525 
526 #define TYPEFORMAT_LINE( obj_type, prop_type, auto_texts, auto_lines ) \
527     { obj_type, prop_type, auto_lines, nullptr,  auto_texts, false }
528 
529 const ObjectTypeFormatEntry spObjTypeFormatEntries[] =
530 {
531     //                object type                property info      auto text          auto line            auto fill
532     TYPEFORMAT_FRAME( OBJECTTYPE_CHARTSPACE,     saCommonPropInfo, nullptr,                 spNoFormats,         spChartSpaceFill ),
533     TYPEFORMAT_FRAME( OBJECTTYPE_CHARTTITLE,     saCommonPropInfo, spChartTitleTexts, nullptr /* eq to Ch2 */,   nullptr /* eq to Ch2 */),
534     TYPEFORMAT_FRAME( OBJECTTYPE_LEGEND,         saCommonPropInfo, spOtherTexts,      spNoFormats,         spNoFormats ),
535     TYPEFORMAT_FRAME( OBJECTTYPE_PLOTAREA2D,     saCommonPropInfo, nullptr,                 nullptr /* eq to Ch2 */,   spPlotArea2dFills ),
536     TYPEFORMAT_FRAME( OBJECTTYPE_PLOTAREA3D,     saCommonPropInfo, nullptr,                 nullptr /* eq to Ch2 */,   nullptr /* eq to Ch2 */ ),
537     TYPEFORMAT_FRAME( OBJECTTYPE_WALL,           saCommonPropInfo, nullptr,                 spWallFloorLines,    spWallFloorFills ),
538     TYPEFORMAT_FRAME( OBJECTTYPE_FLOOR,          saCommonPropInfo, nullptr,                 spWallFloorLines,    spWallFloorFills ),
539     TYPEFORMAT_LINE(  OBJECTTYPE_AXIS,           saCommonPropInfo, spOtherTexts,      spAxisLines ),
540     TYPEFORMAT_FRAME( OBJECTTYPE_AXISTITLE,      saCommonPropInfo, spAxisTitleTexts,  nullptr /* eq to Ch2 */,   nullptr /* eq to Ch2 */ ),
541     TYPEFORMAT_FRAME( OBJECTTYPE_AXISUNIT,       saCommonPropInfo, spAxisTitleTexts,  nullptr /* eq in Ch2 */,   nullptr /* eq in Ch2 */ ),
542     TYPEFORMAT_LINE(  OBJECTTYPE_MAJORGRIDLINE,  saCommonPropInfo, nullptr,                 spMajorGridLines ),
543     TYPEFORMAT_LINE(  OBJECTTYPE_MINORGRIDLINE,  saCommonPropInfo, nullptr,                 spMinorGridLines ),
544     TYPEFORMAT_LINE(  OBJECTTYPE_LINEARSERIES2D, saLinearPropInfo, nullptr,                 spLinearSeriesLines ),
545     TYPEFORMAT_FRAME( OBJECTTYPE_FILLEDSERIES2D, saFilledPropInfo, nullptr,                 spFilledSeriesLines, spFilledSeries2dFills ),
546     TYPEFORMAT_FRAME( OBJECTTYPE_FILLEDSERIES3D, saFilledPropInfo, nullptr,                 spFilledSeriesLines, spFilledSeries3dFills ),
547     TYPEFORMAT_FRAME( OBJECTTYPE_DATALABEL,      saCommonPropInfo, spOtherTexts,      nullptr /* eq to Ch2 */,   nullptr /* eq to Ch2 */ ),
548     TYPEFORMAT_LINE(  OBJECTTYPE_TRENDLINE,      saCommonPropInfo, nullptr,                 spOtherLines ),
549     TYPEFORMAT_FRAME( OBJECTTYPE_TRENDLINELABEL, saCommonPropInfo, spOtherTexts,      nullptr /* eq to Ch2 */,   nullptr /* eq to Ch2 */ ),
550     TYPEFORMAT_LINE(  OBJECTTYPE_ERRORBAR,       saCommonPropInfo, nullptr,                 spOtherLines ),
551     TYPEFORMAT_LINE(  OBJECTTYPE_SERLINE,        saCommonPropInfo, nullptr,                 spOtherLines ),
552     TYPEFORMAT_LINE(  OBJECTTYPE_LEADERLINE,     saCommonPropInfo, nullptr,                 spOtherLines ),
553     TYPEFORMAT_LINE(  OBJECTTYPE_DROPLINE,       saCommonPropInfo, nullptr,                 spOtherLines ),
554     TYPEFORMAT_LINE(  OBJECTTYPE_HILOLINE,       saLinearPropInfo, nullptr,                 spOtherLines ),
555     TYPEFORMAT_FRAME( OBJECTTYPE_UPBAR,          saCommonPropInfo, nullptr,                 spUpDownBarLines,    spUpBarFills ),
556     TYPEFORMAT_FRAME( OBJECTTYPE_DOWNBAR,        saCommonPropInfo, nullptr,                 spUpDownBarLines,    spDownBarFills ),
557     TYPEFORMAT_LINE(  OBJECTTYPE_DATATABLE,      saCommonPropInfo, spOtherTexts,      spDataTableLines )
558 };
559 
560 #undef TYPEFORMAT_FRAME
561 #undef TYPEFORMAT_LINE
562 
lclConvertPictureOptions(FillProperties & orFillProps,const PictureOptionsModel & rPicOptions)563 void lclConvertPictureOptions( FillProperties& orFillProps, const PictureOptionsModel& rPicOptions )
564 {
565     bool bStacked = (rPicOptions.mnPictureFormat == XML_stack) || (rPicOptions.mnPictureFormat == XML_stackScale);
566     orFillProps.maBlipProps.moBitmapMode = bStacked ? XML_tile : XML_stretch;
567 }
568 
569 } // namespace
570 
571 struct ObjectFormatterData;
572 
573 namespace {
574 
575 class DetailFormatterBase
576 {
577 public:
578     explicit            DetailFormatterBase(
579                             ObjectFormatterData& rData,
580                             const AutoFormatEntry* pAutoFormatEntry );
581     explicit            DetailFormatterBase(
582                             ObjectFormatterData& rData,
583                             const AutoTextEntry* pAutoTextEntry );
584 
585 protected:
586     /** Returns the placeholder color which may depend on the passed series index. */
587     ::Color         getPhColor( sal_Int32 nSeriesIdx ) const;
588 
589 private:
590     /** Resolves and returns the scheme color with the passed transformation. */
591     ::Color         getSchemeColor( sal_Int32 nColorToken, sal_Int32 nModToken, sal_Int32 nModValue ) const;
592 
593 protected:
594     typedef ::std::vector< ::Color > ColorPatternVec;
595 
596     ObjectFormatterData& mrData;            /// Shared formatter data.
597     ::Color             mnPhClr;            /// RGB placeholder color for themed style.
598     ColorPatternVec     maColorPattern;     /// Different cycling colors for data series.
599 };
600 
601 class LineFormatter : public DetailFormatterBase
602 {
603 public:
604     explicit            LineFormatter(
605                             ObjectFormatterData& rData,
606                             const AutoFormatEntry* pAutoFormatEntry,
607                             const ObjectType eObjType );
608 
609     /** Converts line formatting to the passed property set. */
610     void                convertFormatting(
611                             ShapePropertyMap& rPropMap,
612                             const ModelRef< Shape >& rxShapeProp,
613                             sal_Int32 nSeriesIdx );
614 
615 private:
616     LinePropertiesPtr   mxAutoLine;         /// Automatic line properties.
617 };
618 
619 class FillFormatter : public DetailFormatterBase
620 {
621 public:
622     explicit            FillFormatter(
623                             ObjectFormatterData& rData,
624                             const AutoFormatEntry* pAutoFormatEntry,
625                             const ObjectType eObjType );
626 
627     /** Converts area formatting to the passed property set. */
628     void                convertFormatting(
629                             ShapePropertyMap& rPropMap,
630                             const ModelRef< Shape >& rxShapeProp,
631                             const PictureOptionsModel* pPicOptions,
632                             sal_Int32 nSeriesIdx );
633 
634 private:
635     FillPropertiesPtr   mxAutoFill;         /// Automatic fill properties.
636 };
637 
638 class TextFormatter : public DetailFormatterBase
639 {
640 public:
641     explicit            TextFormatter(
642                             ObjectFormatterData& rData,
643                             const AutoTextEntry* pAutoTextEntry,
644                             const ModelRef< TextBody >& rxGlobalTextProp );
645 
646     /** Converts text formatting to the passed property set. */
647     void                convertFormatting(
648                             PropertySet& rPropSet,
649                             const TextCharacterProperties* pTextProps );
650     /** Converts text formatting to the passed property set. */
651     void                convertFormatting(
652                             PropertySet& rPropSet,
653                             const ModelRef< TextBody >& rxTextProp );
654 
655 private:
656     TextCharacterPropertiesPtr mxAutoText;  /// Automatic text properties.
657 };
658 
659 /** Formatter for a specific object type. */
660 class ObjectTypeFormatter
661 {
662 public:
663     explicit            ObjectTypeFormatter(
664                             ObjectFormatterData& rData,
665                             const ObjectTypeFormatEntry& rEntry,
666                             const ChartSpaceModel& rChartSpace,
667                             const ObjectType eObjType );
668 
669     /** Sets frame formatting properties to the passed property set. */
670     void                convertFrameFormatting(
671                             PropertySet& rPropSet,
672                             const ModelRef< Shape >& rxShapeProp,
673                             const PictureOptionsModel* pPicOptions,
674                             sal_Int32 nSeriesIdx );
675 
676     /** Sets text formatting properties to the passed property set. */
677     void                convertTextFormatting(
678                             PropertySet& rPropSet,
679                             const ModelRef< TextBody >& rxTextProp );
680 
681     /** Sets frame/text formatting properties to the passed property set. */
682     void                convertFormatting(
683                             PropertySet& rPropSet,
684                             const ModelRef< Shape >& rxShapeProp,
685                             const ModelRef< TextBody >& rxTextProp );
686 
687     /** Sets text formatting properties to the passed property set. */
688     void                convertTextFormatting(
689                             PropertySet& rPropSet,
690                             const TextCharacterProperties& rTextProps );
691 
692     /** Sets automatic fill properties to the passed property set. */
693     void                convertAutomaticFill(
694                             PropertySet& rPropSet,
695                             sal_Int32 nSeriesIdx );
696 
697 private:
698     LineFormatter       maLineFormatter;    /// Converter for line formatting.
699     FillFormatter       maFillFormatter;    /// Converter for fill formatting.
700     TextFormatter       maTextFormatter;    /// Converter for text formatting.
701     ModelObjectHelper&  mrModelObjHelper;   /// Helper for named drawing formatting.
702     const ObjectTypeFormatEntry& mrEntry;   /// Additional settings.
703 };
704 
705 }
706 
707 struct ObjectFormatterData
708 {
709     typedef RefMap< ObjectType, ObjectTypeFormatter > ObjectTypeFormatterMap;
710 
711     const XmlFilterBase& mrFilter;              /// Base filter object.
712     ObjectTypeFormatterMap maTypeFormatters;    /// Formatters for all types of objects in a chart.
713     ModelObjectHelper   maModelObjHelper;       /// Helper for named drawing formatting (dashes, gradients, bitmaps).
714     Reference< XNumberFormats > mxNumFmts;      /// Number formats collection of container document.
715     Reference< XNumberFormatTypes > mxNumTypes; /// Number format types collection of container document.
716     Locale              maEnUsLocale;           /// Locale struct containing en-US.
717     Locale              maFromLocale;           /// Empty locale struct.
718     sal_Int32           mnMaxSeriesIdx;         /// Maximum series index used for color cycling/fading.
719 
720     explicit            ObjectFormatterData(
721                             const XmlFilterBase& rFilter,
722                             const Reference< XChartDocument >& rxChartDoc,
723                             const ChartSpaceModel& rChartSpace );
724 
725     ObjectTypeFormatter* getTypeFormatter( ObjectType eObjType );
726 };
727 
DetailFormatterBase(ObjectFormatterData & rData,const AutoFormatEntry * pAutoFormatEntry)728 DetailFormatterBase::DetailFormatterBase( ObjectFormatterData& rData, const AutoFormatEntry* pAutoFormatEntry ) :
729     mrData( rData ),
730     mnPhClr( ColorTransparency, 0xffffffff )
731 {
732     if( !pAutoFormatEntry )
733         return;
734 
735     if( pAutoFormatEntry->mpPattern )
736     {
737         // prepare multi-color pattern
738         for( const AutoFormatPatternEntry* pPatternEntry = pAutoFormatEntry->mpPattern; pPatternEntry->mnColorToken != XML_TOKEN_INVALID; ++pPatternEntry )
739             maColorPattern.push_back( getSchemeColor( pPatternEntry->mnColorToken, pPatternEntry->mnModToken, pPatternEntry->mnModValue ) );
740     }
741     else if( pAutoFormatEntry->mnColorToken != XML_TOKEN_INVALID )
742     {
743         // prepare color or single-color pattern (color fading)
744         mnPhClr = getSchemeColor( pAutoFormatEntry->mnColorToken, pAutoFormatEntry->mnModToken, pAutoFormatEntry->mnModValue );
745         if( pAutoFormatEntry->mbFadedColor )
746             maColorPattern.push_back( mnPhClr );
747     }
748 }
749 
DetailFormatterBase(ObjectFormatterData & rData,const AutoTextEntry * pAutoTextEntry)750 DetailFormatterBase::DetailFormatterBase( ObjectFormatterData& rData, const AutoTextEntry* pAutoTextEntry ) :
751     mrData( rData ),
752     mnPhClr( ColorTransparency, 0xffffffff )
753 {
754     if( pAutoTextEntry && (pAutoTextEntry->mnColorToken != XML_TOKEN_INVALID) )
755         mnPhClr = getSchemeColor( pAutoTextEntry->mnColorToken, XML_TOKEN_INVALID, 0 );
756 }
757 
getPhColor(sal_Int32 nSeriesIdx) const758 ::Color DetailFormatterBase::getPhColor( sal_Int32 nSeriesIdx ) const
759 {
760     if( maColorPattern.empty() || (mrData.mnMaxSeriesIdx < 0) || (nSeriesIdx < 0) )
761         return mnPhClr;
762 
763     /*  Apply tint/shade depending on the cycle index. The colors of leading
764         series are darkened (color shade), the colors of trailing series are
765         lightened (color tint). Shade/tint is applied in an exclusive range of
766         -70% to 70%.
767 
768         Example 1: 3 data series using single-color shading with accent color 1
769         (e.g. automatic chart style #3). Shade/tint is applied per series.
770         Shade/tint changes in steps of 140%/(<series_count+1) = 140%/4 = 35%,
771         starting at -70%:
772             Step 1: -70% -> Not used.
773             Step 2: -35% -> Series 1 has 35% shade of accent color 1.
774             Step 3:   0% -> Series 2 has pure accent color 1.
775             Step 4:  35% -> Series 3 has 35% tint of accent color 1.
776             Step 5:  70% -> Not used.
777 
778         Example 2: 20 data series using accent color pattern (e.g. automatic
779         chart style #2). Each color cycle has a size of 6 series (accent colors
780         1 to 6). Shade/tint is applied per color cycle.
781             Cycle #1: Series 1...6 are based on accent colors 1 to 6.
782             Cycle #2: Series 7...12 are based on accent colors 1 to 6.
783             Cycle #3: Series 13...18 are based on accent colors 1 to 6.
784             Cycle #4: Series 19...20 are based on accent colors 1 to 2.
785         Shade/tint changes in steps of 140%/(cycle_count+1) = 140%/5 = 28%,
786         starting at -70%:
787             Step 1: -70% -> Not used.
788             Step 2: -42% -> Cycle #1 has 42% shade of accent colors 1...6
789             step 3: -14% -> Cycle #2 has 14% shade of accent colors 1...6
790             step 4:  14% -> Cycle #3 has 14% tint of accent colors 1...6
791             step 5:  42% -> Cycle #4 has 42% tint of accent colors 1...6
792             step 6:  70% -> Not used.
793      */
794     ::Color nPhClr = maColorPattern[ static_cast< size_t >( nSeriesIdx % maColorPattern.size() ) ];
795     size_t nCycleIdx = static_cast< size_t >( nSeriesIdx / maColorPattern.size() );
796     size_t nMaxCycleIdx = static_cast< size_t >( mrData.mnMaxSeriesIdx / maColorPattern.size() );
797     double fShadeTint = static_cast< double >( nCycleIdx + 1 ) / (nMaxCycleIdx + 2) * 1.4 - 0.7;
798     if( fShadeTint != 0.0 )
799     {
800         Color aColor;
801         aColor.setSrgbClr( nPhClr );
802         aColor.addChartTintTransformation( fShadeTint );
803         nPhClr = aColor.getColor( mrData.mrFilter.getGraphicHelper() );
804     }
805 
806     return nPhClr;
807 }
808 
getSchemeColor(sal_Int32 nColorToken,sal_Int32 nModToken,sal_Int32 nModValue) const809 ::Color DetailFormatterBase::getSchemeColor( sal_Int32 nColorToken, sal_Int32 nModToken, sal_Int32 nModValue ) const
810 {
811     Color aColor;
812     aColor.setSchemeClr( nColorToken );
813     if( nModToken != XML_TOKEN_INVALID )
814         aColor.addTransformation( nModToken, nModValue );
815     return aColor.getColor( mrData.mrFilter.getGraphicHelper() );
816 }
817 
LineFormatter(ObjectFormatterData & rData,const AutoFormatEntry * pAutoFormatEntry,const ObjectType eObjType)818 LineFormatter::LineFormatter( ObjectFormatterData& rData, const AutoFormatEntry* pAutoFormatEntry, const ObjectType eObjType ) :
819    DetailFormatterBase(rData, pAutoFormatEntry)
820 {
821     if( !pAutoFormatEntry )
822         return;
823 
824     mxAutoLine = std::make_shared<LineProperties>();
825     mxAutoLine->maLineFill.moFillType = XML_noFill;
826     if( const Theme* pTheme = mrData.mrFilter.getCurrentTheme() )
827         if( const LineProperties* pLineProps = pTheme->getLineStyle( pAutoFormatEntry->mnThemedIdx ) )
828             *mxAutoLine = *pLineProps;
829     // set automatic border property for chartarea, because of tdf#81437 and tdf#82217
830     if ( eObjType == OBJECTTYPE_CHARTSPACE )
831     {
832         mxAutoLine->maLineFill.moFillType = oox::GraphicHelper::getDefaultChartAreaLineStyle();
833         mxAutoLine->moLineWidth = oox::GraphicHelper::getDefaultChartAreaLineWidth();
834         // this value is what MSO 2016 use as a default color for chartspace border
835         mxAutoLine->maLineFill.maFillColor.setSrgbClr( 0xD9D9D9 );
836     }
837     // change line width according to chart auto style
838     if( mxAutoLine->moLineWidth.has() )
839         mxAutoLine->moLineWidth = mxAutoLine->moLineWidth.get() * pAutoFormatEntry->mnRelLineWidth / 100;
840 }
841 
convertFormatting(ShapePropertyMap & rPropMap,const ModelRef<Shape> & rxShapeProp,sal_Int32 nSeriesIdx)842 void LineFormatter::convertFormatting( ShapePropertyMap& rPropMap, const ModelRef< Shape >& rxShapeProp, sal_Int32 nSeriesIdx )
843 {
844     LineProperties aLineProps;
845     if( mxAutoLine )
846         aLineProps.assignUsed( *mxAutoLine );
847     if( rxShapeProp.is() )
848         aLineProps.assignUsed( rxShapeProp->getLineProperties() );
849     aLineProps.pushToPropMap( rPropMap, mrData.mrFilter.getGraphicHelper(), getPhColor( nSeriesIdx ) );
850 }
851 
FillFormatter(ObjectFormatterData & rData,const AutoFormatEntry * pAutoFormatEntry,const ObjectType eObjType)852 FillFormatter::FillFormatter( ObjectFormatterData& rData, const AutoFormatEntry* pAutoFormatEntry, const ObjectType eObjType ) :
853     DetailFormatterBase( rData, pAutoFormatEntry )
854 {
855     if( !pAutoFormatEntry )
856         return;
857 
858     mxAutoFill = std::make_shared<FillProperties>();
859     if( eObjType != OBJECTTYPE_CHARTSPACE )
860         mxAutoFill->moFillType = XML_noFill;
861     if( const Theme* pTheme = mrData.mrFilter.getCurrentTheme() )
862         if( const FillProperties* pFillProps = pTheme->getFillStyle( pAutoFormatEntry->mnThemedIdx ) )
863             *mxAutoFill = *pFillProps;
864 
865     if (eObjType == OBJECTTYPE_CHARTSPACE)
866     {
867         mxAutoFill->moFillType = rData.mrFilter.getGraphicHelper().getDefaultChartAreaFillStyle();
868     }
869 }
870 
convertFormatting(ShapePropertyMap & rPropMap,const ModelRef<Shape> & rxShapeProp,const PictureOptionsModel * pPicOptions,sal_Int32 nSeriesIdx)871 void FillFormatter::convertFormatting( ShapePropertyMap& rPropMap, const ModelRef< Shape >& rxShapeProp, const PictureOptionsModel* pPicOptions, sal_Int32 nSeriesIdx )
872 {
873     FillProperties aFillProps;
874     if( mxAutoFill )
875         aFillProps.assignUsed( *mxAutoFill );
876     if( rxShapeProp.is() )
877         aFillProps.assignUsed( rxShapeProp->getFillProperties() );
878     if( pPicOptions )
879         lclConvertPictureOptions( aFillProps, *pPicOptions );
880     aFillProps.pushToPropMap( rPropMap, mrData.mrFilter.getGraphicHelper(), 0, getPhColor( nSeriesIdx ) );
881 }
882 
883 namespace {
884 
lclGetTextProperties(const ModelRef<TextBody> & rxTextProp)885 const TextCharacterProperties* lclGetTextProperties( const ModelRef< TextBody >& rxTextProp )
886 {
887     return (rxTextProp.is() && !rxTextProp->getParagraphs().empty()) ?
888         &rxTextProp->getParagraphs().front()->getProperties().getTextCharacterProperties() : nullptr;
889 }
890 
891 } // namespace
892 
TextFormatter(ObjectFormatterData & rData,const AutoTextEntry * pAutoTextEntry,const ModelRef<TextBody> & rxGlobalTextProp)893 TextFormatter::TextFormatter( ObjectFormatterData& rData, const AutoTextEntry* pAutoTextEntry, const ModelRef< TextBody >& rxGlobalTextProp ) :
894     DetailFormatterBase( rData, pAutoTextEntry )
895 {
896     if( !pAutoTextEntry )
897         return;
898 
899     mxAutoText = std::make_shared<TextCharacterProperties>();
900     if( const Theme* pTheme = mrData.mrFilter.getCurrentTheme() )
901         if( const TextCharacterProperties* pTextProps = pTheme->getFontStyle( pAutoTextEntry->mnThemedFont ) )
902             *mxAutoText = *pTextProps;
903     ::Color nTextColor = getPhColor( -1 );
904     if( sal_Int32(nTextColor) >= 0 ) {
905         mxAutoText->maFillProperties.maFillColor.setSrgbClr( nTextColor );
906         mxAutoText->maFillProperties.moFillType.set(XML_solidFill);
907     }
908     mxAutoText->moHeight = pAutoTextEntry->mnDefFontSize;
909     mxAutoText->moBold = pAutoTextEntry->mbBold;
910 
911     if( const TextCharacterProperties* pTextProps = lclGetTextProperties( rxGlobalTextProp ) )
912     {
913         mxAutoText->assignUsed( *pTextProps );
914         if( pTextProps->moHeight.has() )
915             mxAutoText->moHeight = pTextProps->moHeight.get() * pAutoTextEntry->mnRelFontSize / 100;
916     }
917 }
918 
convertFormatting(PropertySet & rPropSet,const TextCharacterProperties * pTextProps)919 void TextFormatter::convertFormatting( PropertySet& rPropSet, const TextCharacterProperties* pTextProps )
920 {
921     TextCharacterProperties aTextProps;
922     if( mxAutoText )
923         aTextProps.assignUsed( *mxAutoText );
924     if( pTextProps )
925         aTextProps.assignUsed( *pTextProps );
926     aTextProps.pushToPropSet( rPropSet, mrData.mrFilter );
927 }
928 
convertFormatting(PropertySet & rPropSet,const ModelRef<TextBody> & rxTextProp)929 void TextFormatter::convertFormatting( PropertySet& rPropSet, const ModelRef< TextBody >& rxTextProp )
930 {
931     convertFormatting( rPropSet, lclGetTextProperties( rxTextProp ) );
932 }
933 
ObjectTypeFormatter(ObjectFormatterData & rData,const ObjectTypeFormatEntry & rEntry,const ChartSpaceModel & rChartSpace,const ObjectType eObjType)934 ObjectTypeFormatter::ObjectTypeFormatter( ObjectFormatterData& rData, const ObjectTypeFormatEntry& rEntry, const ChartSpaceModel& rChartSpace, const ObjectType eObjType ) :
935     maLineFormatter(   rData, lclGetAutoFormatEntry( rEntry.mpAutoLines,   rChartSpace.mnStyle ), eObjType ),
936     maFillFormatter(   rData, lclGetAutoFormatEntry( rEntry.mpAutoFills,   rChartSpace.mnStyle ), eObjType ),
937     maTextFormatter(   rData, lclGetAutoTextEntry(   rEntry.mpAutoTexts,   rChartSpace.mnStyle ), rChartSpace.mxTextProp ),
938     mrModelObjHelper( rData.maModelObjHelper ),
939     mrEntry( rEntry )
940 {
941 }
942 
convertFrameFormatting(PropertySet & rPropSet,const ModelRef<Shape> & rxShapeProp,const PictureOptionsModel * pPicOptions,sal_Int32 nSeriesIdx)943 void ObjectTypeFormatter::convertFrameFormatting( PropertySet& rPropSet, const ModelRef< Shape >& rxShapeProp, const PictureOptionsModel* pPicOptions, sal_Int32 nSeriesIdx )
944 {
945     ShapePropertyMap aPropMap( mrModelObjHelper, mrEntry.mrPropInfo );
946     maLineFormatter.convertFormatting( aPropMap, rxShapeProp, nSeriesIdx );
947     if( mrEntry.mbIsFrame )
948         maFillFormatter.convertFormatting( aPropMap, rxShapeProp, pPicOptions, nSeriesIdx );
949     rPropSet.setProperties( aPropMap );
950 }
951 
convertTextFormatting(PropertySet & rPropSet,const ModelRef<TextBody> & rxTextProp)952 void ObjectTypeFormatter::convertTextFormatting( PropertySet& rPropSet, const ModelRef< TextBody >& rxTextProp )
953 {
954     maTextFormatter.convertFormatting( rPropSet, rxTextProp );
955 }
956 
convertFormatting(PropertySet & rPropSet,const ModelRef<Shape> & rxShapeProp,const ModelRef<TextBody> & rxTextProp)957 void ObjectTypeFormatter::convertFormatting( PropertySet& rPropSet, const ModelRef< Shape >& rxShapeProp, const ModelRef< TextBody >& rxTextProp )
958 {
959     convertFrameFormatting( rPropSet, rxShapeProp, nullptr, -1 );
960     convertTextFormatting( rPropSet, rxTextProp );
961 }
962 
convertTextFormatting(PropertySet & rPropSet,const TextCharacterProperties & rTextProps)963 void ObjectTypeFormatter::convertTextFormatting( PropertySet& rPropSet, const TextCharacterProperties& rTextProps )
964 {
965     maTextFormatter.convertFormatting( rPropSet, &rTextProps );
966 }
967 
convertAutomaticFill(PropertySet & rPropSet,sal_Int32 nSeriesIdx)968 void ObjectTypeFormatter::convertAutomaticFill( PropertySet& rPropSet, sal_Int32 nSeriesIdx )
969 {
970     ShapePropertyMap aPropMap( mrModelObjHelper, mrEntry.mrPropInfo );
971     ModelRef< Shape > xShapeProp;
972     maFillFormatter.convertFormatting( aPropMap, xShapeProp, nullptr, nSeriesIdx );
973     rPropSet.setProperties( aPropMap );
974 }
975 
ObjectFormatterData(const XmlFilterBase & rFilter,const Reference<XChartDocument> & rxChartDoc,const ChartSpaceModel & rChartSpace)976 ObjectFormatterData::ObjectFormatterData( const XmlFilterBase& rFilter, const Reference< XChartDocument >& rxChartDoc, const ChartSpaceModel& rChartSpace ) :
977     mrFilter( rFilter ),
978     maModelObjHelper( Reference< XMultiServiceFactory >( rxChartDoc, UNO_QUERY ) ),
979     maEnUsLocale( "en", "US", OUString() ),
980     mnMaxSeriesIdx( -1 )
981 {
982     for(auto const &rEntry : spObjTypeFormatEntries)
983         maTypeFormatters[ rEntry.meObjType ] = std::make_shared<ObjectTypeFormatter>( *this, rEntry, rChartSpace, rEntry.meObjType );
984 
985     try
986     {
987         Reference< XNumberFormatsSupplier > xNumFmtsSupp( rxChartDoc, UNO_QUERY_THROW );
988         mxNumFmts = xNumFmtsSupp->getNumberFormats();
989         mxNumTypes.set( mxNumFmts, UNO_QUERY );
990     }
991     catch( Exception& )
992     {
993     }
994     OSL_ENSURE( mxNumFmts.is() && mxNumTypes.is(), "ObjectFormatterData::ObjectFormatterData - cannot get number formats" );
995 }
996 
getTypeFormatter(ObjectType eObjType)997 ObjectTypeFormatter* ObjectFormatterData::getTypeFormatter( ObjectType eObjType )
998 {
999     OSL_ENSURE( maTypeFormatters.has( eObjType ), "ObjectFormatterData::getTypeFormatter - unknown object type" );
1000     return maTypeFormatters.get( eObjType ).get();
1001 }
1002 
ObjectFormatter(const XmlFilterBase & rFilter,const Reference<XChartDocument> & rxChartDoc,const ChartSpaceModel & rChartSpace)1003 ObjectFormatter::ObjectFormatter( const XmlFilterBase& rFilter, const Reference< XChartDocument >& rxChartDoc, const ChartSpaceModel& rChartSpace ) :
1004     mxData( std::make_shared<ObjectFormatterData>( rFilter, rxChartDoc, rChartSpace ) )
1005 {
1006 }
1007 
~ObjectFormatter()1008 ObjectFormatter::~ObjectFormatter()
1009 {
1010 }
1011 
setMaxSeriesIndex(sal_Int32 nMaxSeriesIdx)1012 void ObjectFormatter::setMaxSeriesIndex( sal_Int32 nMaxSeriesIdx )
1013 {
1014     mxData->mnMaxSeriesIdx = nMaxSeriesIdx;
1015 }
1016 
getMaxSeriesIndex() const1017 sal_Int32 ObjectFormatter::getMaxSeriesIndex() const
1018 {
1019     return mxData->mnMaxSeriesIdx;
1020 }
1021 
convertFrameFormatting(PropertySet & rPropSet,const ModelRef<Shape> & rxShapeProp,ObjectType eObjType,sal_Int32 nSeriesIdx)1022 void ObjectFormatter::convertFrameFormatting( PropertySet& rPropSet, const ModelRef< Shape >& rxShapeProp, ObjectType eObjType, sal_Int32 nSeriesIdx )
1023 {
1024     if( ObjectTypeFormatter* pFormat = mxData->getTypeFormatter( eObjType ) )
1025         pFormat->convertFrameFormatting( rPropSet, rxShapeProp, nullptr, nSeriesIdx );
1026 }
1027 
convertFrameFormatting(PropertySet & rPropSet,const ModelRef<Shape> & rxShapeProp,const PictureOptionsModel & rPicOptions,ObjectType eObjType,sal_Int32 nSeriesIdx)1028 void ObjectFormatter::convertFrameFormatting( PropertySet& rPropSet, const ModelRef< Shape >& rxShapeProp, const PictureOptionsModel& rPicOptions, ObjectType eObjType, sal_Int32 nSeriesIdx )
1029 {
1030     if( ObjectTypeFormatter* pFormat = mxData->getTypeFormatter( eObjType ) )
1031         pFormat->convertFrameFormatting( rPropSet, rxShapeProp, &rPicOptions, nSeriesIdx );
1032 }
1033 
convertTextFormatting(PropertySet & rPropSet,const ModelRef<TextBody> & rxTextProp,ObjectType eObjType)1034 void ObjectFormatter::convertTextFormatting( PropertySet& rPropSet, const ModelRef< TextBody >& rxTextProp, ObjectType eObjType )
1035 {
1036     if( ObjectTypeFormatter* pFormat = mxData->getTypeFormatter( eObjType ) )
1037         pFormat->convertTextFormatting( rPropSet, rxTextProp );
1038 }
1039 
convertFormatting(PropertySet & rPropSet,const ModelRef<Shape> & rxShapeProp,const ModelRef<TextBody> & rxTextProp,ObjectType eObjType)1040 void ObjectFormatter::convertFormatting( PropertySet& rPropSet, const ModelRef< Shape >& rxShapeProp, const ModelRef< TextBody >& rxTextProp, ObjectType eObjType )
1041 {
1042     if( ObjectTypeFormatter* pFormat = mxData->getTypeFormatter( eObjType ) )
1043         pFormat->convertFormatting( rPropSet, rxShapeProp, rxTextProp );
1044 }
1045 
convertTextFormatting(PropertySet & rPropSet,const TextCharacterProperties & rTextProps,ObjectType eObjType)1046 void ObjectFormatter::convertTextFormatting( PropertySet& rPropSet, const TextCharacterProperties& rTextProps, ObjectType eObjType )
1047 {
1048     if( ObjectTypeFormatter* pFormat = mxData->getTypeFormatter( eObjType ) )
1049         pFormat->convertTextFormatting( rPropSet, rTextProps );
1050 }
1051 
convertTextRotation(PropertySet & rPropSet,const ModelRef<TextBody> & rxTextProp,bool bSupportsStacked,sal_Int32 nDefaultRotation)1052 void ObjectFormatter::convertTextRotation( PropertySet& rPropSet, const ModelRef< TextBody >& rxTextProp, bool bSupportsStacked, sal_Int32 nDefaultRotation )
1053 {
1054     if( !rxTextProp.is() )
1055         return;
1056 
1057     bool bStacked = false;
1058     if( bSupportsStacked )
1059     {
1060         sal_Int32 nVert = rxTextProp->getTextProperties().moVert.get( XML_horz );
1061         bStacked = (nVert == XML_wordArtVert) || (nVert == XML_wordArtVertRtl);
1062         rPropSet.setProperty( PROP_StackCharacters, bStacked );
1063     }
1064 
1065     /*  Chart2 expects rotation angle as double value in range of [0,360).
1066         OOXML counts clockwise, Chart2 counts counterclockwise. */
1067     double fAngle = static_cast< double >( bStacked ? 0 : rxTextProp->getTextProperties().moRotation.get( nDefaultRotation ) );
1068     // MS Office UI allows values only in range of [-90,90].
1069     if ( fAngle < -5400000.0 || fAngle > 5400000.0 )
1070     {
1071         fAngle = 0.0;
1072     }
1073     fAngle = getDoubleIntervalValue< double >( -fAngle / 60000.0, 0.0, 360.0 );
1074     rPropSet.setProperty( PROP_TextRotation, fAngle );
1075 }
1076 
convertTextWrap(PropertySet & rPropSet,const ModelRef<TextBody> & rxTextProp)1077 void ObjectFormatter::convertTextWrap( PropertySet& rPropSet, const ModelRef< TextBody >& rxTextProp )
1078 {
1079     if( !rxTextProp.is() )
1080     {
1081         // set default value (in OOXML the default value is true)
1082         rPropSet.setProperty( PROP_TextWordWrap, true );
1083         return;
1084     }
1085 
1086     PropertyMap& aPropMap = rxTextProp->getTextProperties().maPropertyMap;
1087     if( aPropMap.hasProperty(PROP_TextWordWrap) )
1088     {
1089         Any aValue = aPropMap.getProperty( PROP_TextWordWrap );
1090         if( aValue.hasValue() )
1091         {
1092             bool bValue = false;
1093             aValue >>= bValue;
1094             rPropSet.setProperty( PROP_TextWordWrap, bValue );
1095         }
1096     }
1097 }
1098 
convertNumberFormat(PropertySet & rPropSet,const NumberFormat & rNumberFormat,bool bAxis,bool bShowPercent)1099 void ObjectFormatter::convertNumberFormat( PropertySet& rPropSet, const NumberFormat& rNumberFormat, bool bAxis, bool bShowPercent )
1100 {
1101     if( !mxData->mxNumFmts.is() )
1102         return;
1103 
1104     const bool bGeneral = rNumberFormat.maFormatCode.equalsIgnoreAsciiCase("general");
1105     const bool bPercent = !bAxis && bShowPercent && !rNumberFormat.mbSourceLinked;
1106     sal_Int32 nPropId = bPercent ? PROP_PercentageNumberFormat : PROP_NumberFormat;
1107     OUString sFormatCode(rNumberFormat.maFormatCode);
1108     if (bPercent && bGeneral)
1109         sFormatCode = "0%";
1110     try
1111     {
1112         sal_Int32 nIndex = bGeneral && !bPercent ?
1113             mxData->mxNumTypes->getStandardIndex( mxData->maFromLocale ) :
1114             mxData->mxNumFmts->addNewConverted( sFormatCode, mxData->maEnUsLocale, mxData->maFromLocale );
1115         if( nIndex >= 0 )
1116             rPropSet.setProperty( nPropId, nIndex );
1117     }
1118     catch( Exception& )
1119     {
1120         OSL_FAIL( OStringBuffer( "ObjectFormatter::convertNumberFormat - cannot create number format '" +
1121                 OUStringToOString( rNumberFormat.maFormatCode, osl_getThreadTextEncoding() )  + "'" ).getStr() );
1122     }
1123 
1124     // Setting "LinkNumberFormatToSource" does not really work, at least not for axis :-/
1125     if (!bAxis)
1126         rPropSet.setProperty(PROP_LinkNumberFormatToSource, makeAny(rNumberFormat.mbSourceLinked));
1127     else
1128         rPropSet.setProperty(PROP_LinkNumberFormatToSource, makeAny(rNumberFormat.maFormatCode.isEmpty()));
1129 }
1130 
convertAutomaticFill(PropertySet & rPropSet,ObjectType eObjType,sal_Int32 nSeriesIdx)1131 void ObjectFormatter::convertAutomaticFill( PropertySet& rPropSet, ObjectType eObjType, sal_Int32 nSeriesIdx )
1132 {
1133     if( ObjectTypeFormatter* pFormat = mxData->getTypeFormatter( eObjType ) )
1134         pFormat->convertAutomaticFill( rPropSet, nSeriesIdx );
1135 }
1136 
isAutomaticFill(const ModelRef<Shape> & rxShapeProp)1137 bool ObjectFormatter::isAutomaticFill( const ModelRef< Shape >& rxShapeProp )
1138 {
1139     return !rxShapeProp || !rxShapeProp->getFillProperties().moFillType.has();
1140 }
1141 
1142 } // namespace oox
1143 
1144 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
1145