xlsxwriter 0.0.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (112) hide show
  1. checksums.yaml +7 -0
  2. data/Rakefile +40 -0
  3. data/ext/xlsxwriter/chart.c +105 -0
  4. data/ext/xlsxwriter/chart.h +27 -0
  5. data/ext/xlsxwriter/extconf.rb +14 -0
  6. data/ext/xlsxwriter/format.c +67 -0
  7. data/ext/xlsxwriter/format.h +9 -0
  8. data/ext/xlsxwriter/libxlsxwriter/LICENSE.txt +89 -0
  9. data/ext/xlsxwriter/libxlsxwriter/Makefile +141 -0
  10. data/ext/xlsxwriter/libxlsxwriter/include/xlsxwriter.h +23 -0
  11. data/ext/xlsxwriter/libxlsxwriter/include/xlsxwriter/app.h +79 -0
  12. data/ext/xlsxwriter/libxlsxwriter/include/xlsxwriter/chart.h +1093 -0
  13. data/ext/xlsxwriter/libxlsxwriter/include/xlsxwriter/common.h +336 -0
  14. data/ext/xlsxwriter/libxlsxwriter/include/xlsxwriter/content_types.h +74 -0
  15. data/ext/xlsxwriter/libxlsxwriter/include/xlsxwriter/core.h +51 -0
  16. data/ext/xlsxwriter/libxlsxwriter/include/xlsxwriter/custom.h +52 -0
  17. data/ext/xlsxwriter/libxlsxwriter/include/xlsxwriter/drawing.h +111 -0
  18. data/ext/xlsxwriter/libxlsxwriter/include/xlsxwriter/format.h +1214 -0
  19. data/ext/xlsxwriter/libxlsxwriter/include/xlsxwriter/hash_table.h +76 -0
  20. data/ext/xlsxwriter/libxlsxwriter/include/xlsxwriter/packager.h +80 -0
  21. data/ext/xlsxwriter/libxlsxwriter/include/xlsxwriter/relationships.h +77 -0
  22. data/ext/xlsxwriter/libxlsxwriter/include/xlsxwriter/shared_strings.h +83 -0
  23. data/ext/xlsxwriter/libxlsxwriter/include/xlsxwriter/styles.h +77 -0
  24. data/ext/xlsxwriter/libxlsxwriter/include/xlsxwriter/theme.h +47 -0
  25. data/ext/xlsxwriter/libxlsxwriter/include/xlsxwriter/third_party/ioapi.h +215 -0
  26. data/ext/xlsxwriter/libxlsxwriter/include/xlsxwriter/third_party/queue.h +694 -0
  27. data/ext/xlsxwriter/libxlsxwriter/include/xlsxwriter/third_party/tmpfileplus.h +53 -0
  28. data/ext/xlsxwriter/libxlsxwriter/include/xlsxwriter/third_party/tree.h +801 -0
  29. data/ext/xlsxwriter/libxlsxwriter/include/xlsxwriter/third_party/zip.h +375 -0
  30. data/ext/xlsxwriter/libxlsxwriter/include/xlsxwriter/utility.h +166 -0
  31. data/ext/xlsxwriter/libxlsxwriter/include/xlsxwriter/workbook.h +751 -0
  32. data/ext/xlsxwriter/libxlsxwriter/include/xlsxwriter/worksheet.h +2641 -0
  33. data/ext/xlsxwriter/libxlsxwriter/include/xlsxwriter/xmlwriter.h +178 -0
  34. data/ext/xlsxwriter/libxlsxwriter/lib/.gitignore +0 -0
  35. data/ext/xlsxwriter/libxlsxwriter/src/Makefile +125 -0
  36. data/ext/xlsxwriter/libxlsxwriter/src/app.c +439 -0
  37. data/ext/xlsxwriter/libxlsxwriter/src/chart.c +3420 -0
  38. data/ext/xlsxwriter/libxlsxwriter/src/content_types.c +341 -0
  39. data/ext/xlsxwriter/libxlsxwriter/src/core.c +293 -0
  40. data/ext/xlsxwriter/libxlsxwriter/src/custom.c +224 -0
  41. data/ext/xlsxwriter/libxlsxwriter/src/drawing.c +746 -0
  42. data/ext/xlsxwriter/libxlsxwriter/src/format.c +728 -0
  43. data/ext/xlsxwriter/libxlsxwriter/src/hash_table.c +223 -0
  44. data/ext/xlsxwriter/libxlsxwriter/src/packager.c +877 -0
  45. data/ext/xlsxwriter/libxlsxwriter/src/relationships.c +242 -0
  46. data/ext/xlsxwriter/libxlsxwriter/src/shared_strings.c +264 -0
  47. data/ext/xlsxwriter/libxlsxwriter/src/styles.c +1086 -0
  48. data/ext/xlsxwriter/libxlsxwriter/src/theme.c +348 -0
  49. data/ext/xlsxwriter/libxlsxwriter/src/utility.c +512 -0
  50. data/ext/xlsxwriter/libxlsxwriter/src/workbook.c +1895 -0
  51. data/ext/xlsxwriter/libxlsxwriter/src/worksheet.c +4992 -0
  52. data/ext/xlsxwriter/libxlsxwriter/src/xmlwriter.c +355 -0
  53. data/ext/xlsxwriter/libxlsxwriter/third_party/minizip/Makefile +44 -0
  54. data/ext/xlsxwriter/libxlsxwriter/third_party/minizip/crypt.h +131 -0
  55. data/ext/xlsxwriter/libxlsxwriter/third_party/minizip/ioapi.c +247 -0
  56. data/ext/xlsxwriter/libxlsxwriter/third_party/minizip/ioapi.h +209 -0
  57. data/ext/xlsxwriter/libxlsxwriter/third_party/minizip/iowin32.c +456 -0
  58. data/ext/xlsxwriter/libxlsxwriter/third_party/minizip/iowin32.h +28 -0
  59. data/ext/xlsxwriter/libxlsxwriter/third_party/minizip/miniunz.c +660 -0
  60. data/ext/xlsxwriter/libxlsxwriter/third_party/minizip/minizip.c +520 -0
  61. data/ext/xlsxwriter/libxlsxwriter/third_party/minizip/mztools.c +291 -0
  62. data/ext/xlsxwriter/libxlsxwriter/third_party/minizip/mztools.h +37 -0
  63. data/ext/xlsxwriter/libxlsxwriter/third_party/minizip/unzip.c +2125 -0
  64. data/ext/xlsxwriter/libxlsxwriter/third_party/minizip/unzip.h +437 -0
  65. data/ext/xlsxwriter/libxlsxwriter/third_party/minizip/zip.c +2007 -0
  66. data/ext/xlsxwriter/libxlsxwriter/third_party/minizip/zip.h +367 -0
  67. data/ext/xlsxwriter/libxlsxwriter/third_party/tmpfileplus/Makefile +42 -0
  68. data/ext/xlsxwriter/libxlsxwriter/third_party/tmpfileplus/tmpfileplus.c +342 -0
  69. data/ext/xlsxwriter/libxlsxwriter/third_party/tmpfileplus/tmpfileplus.h +53 -0
  70. data/ext/xlsxwriter/workbook.c +257 -0
  71. data/ext/xlsxwriter/workbook.h +42 -0
  72. data/ext/xlsxwriter/workbook_properties.c +103 -0
  73. data/ext/xlsxwriter/workbook_properties.h +10 -0
  74. data/ext/xlsxwriter/worksheet.c +1064 -0
  75. data/ext/xlsxwriter/worksheet.h +74 -0
  76. data/ext/xlsxwriter/xlsxwriter.c +239 -0
  77. data/lib/xlsxwriter.rb +6 -0
  78. data/lib/xlsxwriter/version.rb +3 -0
  79. data/lib/xlsxwriter/worksheet.rb +72 -0
  80. data/test/run-test.rb +11 -0
  81. data/test/support/xlsx_comparable.rb +109 -0
  82. data/test/test-array-formula.rb +33 -0
  83. data/test/test-autofilter.rb +70 -0
  84. data/test/test-chart-area.rb +25 -0
  85. data/test/test-data.rb +65 -0
  86. data/test/test-default-row.rb +25 -0
  87. data/test/test-defined-name.rb +46 -0
  88. data/test/test-escapes.rb +33 -0
  89. data/test/test-fit-to-pages.rb +21 -0
  90. data/test/test-formatting.rb +137 -0
  91. data/test/test-gridlines.rb +15 -0
  92. data/test/test-hyperlink.rb +67 -0
  93. data/test/test-image.rb +84 -0
  94. data/test/test-merge-range.rb +18 -0
  95. data/test/test-misc.rb +29 -0
  96. data/test/test-optimize.rb +32 -0
  97. data/test/test-page-breaks.rb +13 -0
  98. data/test/test-page-setup.rb +28 -0
  99. data/test/test-panes.rb +45 -0
  100. data/test/test-print-area.rb +19 -0
  101. data/test/test-print-options.rb +61 -0
  102. data/test/test-print-scale.rb +12 -0
  103. data/test/test-properties.rb +51 -0
  104. data/test/test-protect.rb +27 -0
  105. data/test/test-repeat.rb +23 -0
  106. data/test/test-row-col-format.rb +35 -0
  107. data/test/test-set-selection.rb +13 -0
  108. data/test/test-set-start-page.rb +13 -0
  109. data/test/test-simple.rb +62 -0
  110. data/test/test-types.rb +17 -0
  111. data/test/xlsx-func-testcase.rb +36 -0
  112. metadata +228 -0
@@ -0,0 +1,3420 @@
1
+ /*****************************************************************************
2
+ * chart - A library for creating Excel XLSX chart files.
3
+ *
4
+ * Used in conjunction with the libxlsxwriter library.
5
+ *
6
+ * Copyright 2014-2017, John McNamara, jmcnamara@cpan.org. See LICENSE.txt.
7
+ *
8
+ */
9
+
10
+ #include "xlsxwriter/xmlwriter.h"
11
+ #include "xlsxwriter/chart.h"
12
+ #include "xlsxwriter/utility.h"
13
+
14
+ /*
15
+ * Forward declarations.
16
+ */
17
+
18
+ /*****************************************************************************
19
+ *
20
+ * Private functions.
21
+ *
22
+ ****************************************************************************/
23
+
24
+ /*
25
+ * Free a series range object.
26
+ */
27
+ STATIC void
28
+ _chart_free_range(lxw_series_range *range)
29
+ {
30
+ struct lxw_series_data_point *data_point;
31
+
32
+ if (!range)
33
+ return;
34
+
35
+ while (!STAILQ_EMPTY(range->data_cache)) {
36
+ data_point = STAILQ_FIRST(range->data_cache);
37
+ free(data_point->string);
38
+ STAILQ_REMOVE_HEAD(range->data_cache, list_pointers);
39
+
40
+ free(data_point);
41
+ }
42
+
43
+ free(range->data_cache);
44
+ free(range->formula);
45
+ free(range->sheetname);
46
+ free(range);
47
+ }
48
+
49
+ /*
50
+ * Free a series object.
51
+ */
52
+ STATIC void
53
+ _chart_series_free(lxw_chart_series *series)
54
+ {
55
+ if (!series)
56
+ return;
57
+
58
+ free(series->title.name);
59
+ free(series->line);
60
+ free(series->fill);
61
+
62
+ _chart_free_range(series->categories);
63
+ _chart_free_range(series->values);
64
+ _chart_free_range(series->title.range);
65
+
66
+ free(series);
67
+ }
68
+
69
+ /*
70
+ * Initialize the data cache in a range object.
71
+ */
72
+ STATIC int
73
+ _chart_init_data_cache(lxw_series_range *range)
74
+ {
75
+ /* Initialize the series range data cache. */
76
+ range->data_cache = calloc(1, sizeof(struct lxw_series_data_points));
77
+ RETURN_ON_MEM_ERROR(range->data_cache, -1);
78
+ STAILQ_INIT(range->data_cache);
79
+
80
+ return 0;
81
+ }
82
+
83
+ /*
84
+ * Free a chart font object.
85
+ */
86
+ STATIC void
87
+ _chart_free_font(lxw_chart_font *font)
88
+ {
89
+ if (!font)
90
+ return;
91
+
92
+ free(font->name);
93
+ free(font);
94
+ }
95
+
96
+ /*
97
+ * Free a chart object.
98
+ */
99
+ void
100
+ lxw_chart_free(lxw_chart *chart)
101
+ {
102
+ lxw_chart_series *series;
103
+
104
+ if (!chart)
105
+ return;
106
+
107
+ /* Chart series. */
108
+ if (chart->series_list) {
109
+ while (!STAILQ_EMPTY(chart->series_list)) {
110
+ series = STAILQ_FIRST(chart->series_list);
111
+ STAILQ_REMOVE_HEAD(chart->series_list, list_pointers);
112
+
113
+ _chart_series_free(series);
114
+ }
115
+
116
+ free(chart->series_list);
117
+ }
118
+
119
+ /* X Axis. */
120
+ if (chart->x_axis) {
121
+ _chart_free_font(chart->x_axis->title.font);
122
+ _chart_free_font(chart->x_axis->num_font);
123
+ _chart_free_range(chart->x_axis->title.range);
124
+ free(chart->x_axis->title.name);
125
+ free(chart->x_axis->line);
126
+ free(chart->x_axis->fill);
127
+ free(chart->x_axis);
128
+ }
129
+
130
+ /* Y Axis. */
131
+ if (chart->y_axis) {
132
+ _chart_free_font(chart->y_axis->title.font);
133
+ _chart_free_font(chart->y_axis->num_font);
134
+ _chart_free_range(chart->y_axis->title.range);
135
+ free(chart->y_axis->title.name);
136
+ free(chart->y_axis->line);
137
+ free(chart->y_axis->fill);
138
+ free(chart->y_axis);
139
+ }
140
+
141
+ /* Chart title. */
142
+ _chart_free_font(chart->title.font);
143
+ _chart_free_range(chart->title.range);
144
+ free(chart->title.name);
145
+
146
+ /* Chart legend. */
147
+ _chart_free_font(chart->legend.font);
148
+ free(chart->delete_series);
149
+
150
+ free(chart);
151
+ }
152
+
153
+ /*
154
+ * Create a new chart object.
155
+ */
156
+ lxw_chart *
157
+ lxw_chart_new(uint8_t type)
158
+ {
159
+ lxw_chart *chart = calloc(1, sizeof(lxw_chart));
160
+ GOTO_LABEL_ON_MEM_ERROR(chart, mem_error);
161
+
162
+ chart->series_list = calloc(1, sizeof(struct lxw_chart_series_list));
163
+ GOTO_LABEL_ON_MEM_ERROR(chart->series_list, mem_error);
164
+ STAILQ_INIT(chart->series_list);
165
+
166
+ chart->x_axis = calloc(1, sizeof(struct lxw_chart_axis));
167
+ GOTO_LABEL_ON_MEM_ERROR(chart->x_axis, mem_error);
168
+
169
+ chart->y_axis = calloc(1, sizeof(struct lxw_chart_axis));
170
+ GOTO_LABEL_ON_MEM_ERROR(chart->y_axis, mem_error);
171
+
172
+ chart->title.range = calloc(1, sizeof(lxw_series_range));
173
+ GOTO_LABEL_ON_MEM_ERROR(chart->title.range, mem_error);
174
+
175
+ chart->x_axis->title.range = calloc(1, sizeof(lxw_series_range));
176
+ GOTO_LABEL_ON_MEM_ERROR(chart->x_axis->title.range, mem_error);
177
+
178
+ chart->y_axis->title.range = calloc(1, sizeof(lxw_series_range));
179
+ GOTO_LABEL_ON_MEM_ERROR(chart->y_axis->title.range, mem_error);
180
+
181
+ /* Initialize the ranges in the chart titles. */
182
+ if (_chart_init_data_cache(chart->title.range) != LXW_NO_ERROR)
183
+ goto mem_error;
184
+
185
+ if (_chart_init_data_cache(chart->x_axis->title.range) != LXW_NO_ERROR)
186
+ goto mem_error;
187
+
188
+ if (_chart_init_data_cache(chart->y_axis->title.range) != LXW_NO_ERROR)
189
+ goto mem_error;
190
+
191
+ chart->type = type;
192
+ chart->style_id = 2;
193
+ chart->hole_size = 50;
194
+
195
+ /* Set the default axis positions. */
196
+ chart->cat_axis_position = LXW_CHART_AXIS_BOTTOM;
197
+ chart->val_axis_position = LXW_CHART_AXIS_LEFT;
198
+
199
+ lxw_strcpy(chart->x_axis->default_num_format, "General");
200
+ lxw_strcpy(chart->y_axis->default_num_format, "General");
201
+
202
+ chart->x_axis->default_major_gridlines = LXW_FALSE;
203
+ chart->y_axis->default_major_gridlines = LXW_TRUE;
204
+
205
+ chart->series_overlap_1 = 100;
206
+
207
+ chart->has_horiz_cat_axis = LXW_FALSE;
208
+ chart->has_horiz_val_axis = LXW_TRUE;
209
+
210
+ chart->legend.position = LXW_CHART_LEGEND_RIGHT;
211
+
212
+ return chart;
213
+
214
+ mem_error:
215
+ lxw_chart_free(chart);
216
+ return NULL;
217
+ }
218
+
219
+ /*
220
+ * Create a copy of a user supplied font.
221
+ */
222
+ STATIC lxw_chart_font *
223
+ _chart_convert_font_args(lxw_chart_font *user_font)
224
+ {
225
+ lxw_chart_font *font;
226
+
227
+ if (!user_font)
228
+ return NULL;
229
+
230
+ font = calloc(1, sizeof(struct lxw_chart_font));
231
+ RETURN_ON_MEM_ERROR(font, NULL);
232
+
233
+ memcpy(font, user_font, sizeof(lxw_chart_font));
234
+
235
+ font->name = lxw_strdup(user_font->name);
236
+
237
+ /* Convert font size units. */
238
+ if (font->size)
239
+ font->size = font->size * 100;
240
+
241
+ /* Convert rotation into 60,000ths of a degree. */
242
+ if (font->rotation)
243
+ font->rotation = font->rotation * 60000;
244
+
245
+ if (font->color) {
246
+ font->color = lxw_format_check_color(font->color);
247
+ font->has_color = LXW_TRUE;
248
+ }
249
+
250
+ return font;
251
+ }
252
+
253
+ /*
254
+ * Create a copy of a user supplied line.
255
+ */
256
+ STATIC lxw_chart_line *
257
+ _chart_convert_line_args(lxw_chart_line *user_line)
258
+ {
259
+ lxw_chart_line *line;
260
+
261
+ if (!user_line)
262
+ return NULL;
263
+
264
+ line = calloc(1, sizeof(struct lxw_chart_line));
265
+ RETURN_ON_MEM_ERROR(line, NULL);
266
+
267
+ memcpy(line, user_line, sizeof(lxw_chart_line));
268
+
269
+ if (line->color) {
270
+ line->color = lxw_format_check_color(line->color);
271
+ line->has_color = LXW_TRUE;
272
+ }
273
+
274
+ if (line->transparency > 100)
275
+ line->transparency = 0;
276
+
277
+ return line;
278
+ }
279
+
280
+ /*
281
+ * Create a copy of a user supplied fill.
282
+ */
283
+ STATIC lxw_chart_fill *
284
+ _chart_convert_fill_args(lxw_chart_fill *user_fill)
285
+ {
286
+ lxw_chart_fill *fill;
287
+
288
+ if (!user_fill)
289
+ return NULL;
290
+
291
+ fill = calloc(1, sizeof(struct lxw_chart_fill));
292
+ RETURN_ON_MEM_ERROR(fill, NULL);
293
+
294
+ memcpy(fill, user_fill, sizeof(lxw_chart_fill));
295
+
296
+ if (fill->color) {
297
+ fill->color = lxw_format_check_color(fill->color);
298
+ fill->has_color = LXW_TRUE;
299
+ }
300
+
301
+ if (fill->transparency > 100)
302
+ fill->transparency = 0;
303
+
304
+ return fill;
305
+ }
306
+
307
+ /*
308
+ * Add unique ids for primary or secondary axes.
309
+ */
310
+ STATIC void
311
+ _chart_add_axis_ids(lxw_chart *self)
312
+ {
313
+ uint32_t chart_id = 50010000 + self->id;
314
+ uint32_t axis_count = 1;
315
+
316
+ self->axis_id_1 = chart_id + axis_count;
317
+ self->axis_id_2 = self->axis_id_1 + 1;
318
+ }
319
+
320
+ /*
321
+ * Utility function to set a chart range.
322
+ */
323
+ STATIC void
324
+ _chart_set_range(lxw_series_range *range, const char *sheetname,
325
+ lxw_row_t first_row, lxw_col_t first_col,
326
+ lxw_row_t last_row, lxw_col_t last_col)
327
+ {
328
+ char formula[LXW_MAX_FORMULA_RANGE_LENGTH] = { 0 };
329
+
330
+ /* Set the range properties. */
331
+ range->sheetname = lxw_strdup(sheetname);
332
+ range->first_row = first_row;
333
+ range->first_col = first_col;
334
+ range->last_row = last_row;
335
+ range->last_col = last_col;
336
+
337
+ /* Free any existing range. */
338
+ free(range->formula);
339
+
340
+ /* Convert the range properties to a formula like: Sheet1!$A$1:$A$5. */
341
+ lxw_rowcol_to_formula_abs(formula, sheetname,
342
+ first_row, first_col, last_row, last_col);
343
+
344
+ range->formula = lxw_strdup(formula);
345
+ }
346
+
347
+ /*****************************************************************************
348
+ *
349
+ * XML functions.
350
+ *
351
+ ****************************************************************************/
352
+
353
+ /*
354
+ * Write the XML declaration.
355
+ */
356
+ STATIC void
357
+ _chart_xml_declaration(lxw_chart *self)
358
+ {
359
+ lxw_xml_declaration(self->file);
360
+ }
361
+
362
+ /*
363
+ * Write the <c:chartSpace> element.
364
+ */
365
+ STATIC void
366
+ _chart_write_chart_space(lxw_chart *self)
367
+ {
368
+ struct xml_attribute_list attributes;
369
+ struct xml_attribute *attribute;
370
+ char xmlns_c[] = LXW_SCHEMA_DRAWING "/chart";
371
+ char xmlns_a[] = LXW_SCHEMA_DRAWING "/main";
372
+ char xmlns_r[] = LXW_SCHEMA_OFFICEDOC "/relationships";
373
+
374
+ LXW_INIT_ATTRIBUTES();
375
+ LXW_PUSH_ATTRIBUTES_STR("xmlns:c", xmlns_c);
376
+ LXW_PUSH_ATTRIBUTES_STR("xmlns:a", xmlns_a);
377
+ LXW_PUSH_ATTRIBUTES_STR("xmlns:r", xmlns_r);
378
+
379
+ lxw_xml_start_tag(self->file, "c:chartSpace", &attributes);
380
+
381
+ LXW_FREE_ATTRIBUTES();
382
+ }
383
+
384
+ /*
385
+ * Write the <c:lang> element.
386
+ */
387
+ STATIC void
388
+ _chart_write_lang(lxw_chart *self)
389
+ {
390
+ struct xml_attribute_list attributes;
391
+ struct xml_attribute *attribute;
392
+
393
+ LXW_INIT_ATTRIBUTES();
394
+ LXW_PUSH_ATTRIBUTES_STR("val", "en-US");
395
+
396
+ lxw_xml_empty_tag(self->file, "c:lang", &attributes);
397
+
398
+ LXW_FREE_ATTRIBUTES();
399
+ }
400
+
401
+ /*
402
+ * Write the <c:style> element.
403
+ */
404
+ STATIC void
405
+ _chart_write_style(lxw_chart *self)
406
+ {
407
+ struct xml_attribute_list attributes;
408
+ struct xml_attribute *attribute;
409
+
410
+ /* Don"t write an element for the default style, 2. */
411
+ if (self->style_id == 2)
412
+ return;
413
+
414
+ LXW_INIT_ATTRIBUTES();
415
+ LXW_PUSH_ATTRIBUTES_INT("val", self->style_id);
416
+
417
+ lxw_xml_empty_tag(self->file, "c:style", &attributes);
418
+
419
+ LXW_FREE_ATTRIBUTES();
420
+ }
421
+
422
+ /*
423
+ * Write the <c:layout> element.
424
+ */
425
+ STATIC void
426
+ _chart_write_layout(lxw_chart *self)
427
+ {
428
+ lxw_xml_empty_tag(self->file, "c:layout", NULL);
429
+ }
430
+
431
+ /*
432
+ * Write the <c:grouping> element.
433
+ */
434
+ STATIC void
435
+ _chart_write_grouping(lxw_chart *self, uint8_t grouping)
436
+ {
437
+ struct xml_attribute_list attributes;
438
+ struct xml_attribute *attribute;
439
+
440
+ LXW_INIT_ATTRIBUTES();
441
+
442
+ if (grouping == LXW_GROUPING_STANDARD)
443
+ LXW_PUSH_ATTRIBUTES_STR("val", "standard");
444
+ else if (grouping == LXW_GROUPING_PERCENTSTACKED)
445
+ LXW_PUSH_ATTRIBUTES_STR("val", "percentStacked");
446
+ else if (grouping == LXW_GROUPING_STACKED)
447
+ LXW_PUSH_ATTRIBUTES_STR("val", "stacked");
448
+ else
449
+ LXW_PUSH_ATTRIBUTES_STR("val", "clustered");
450
+
451
+ lxw_xml_empty_tag(self->file, "c:grouping", &attributes);
452
+
453
+ LXW_FREE_ATTRIBUTES();
454
+ }
455
+
456
+ /*
457
+ * Write the <c:radarStyle> element.
458
+ */
459
+ STATIC void
460
+ _chart_write_radar_style(lxw_chart *self)
461
+ {
462
+ struct xml_attribute_list attributes;
463
+ struct xml_attribute *attribute;
464
+
465
+ LXW_INIT_ATTRIBUTES();
466
+
467
+ if (self->type == LXW_CHART_RADAR_FILLED)
468
+ LXW_PUSH_ATTRIBUTES_STR("val", "filled");
469
+ else
470
+ LXW_PUSH_ATTRIBUTES_STR("val", "marker");
471
+
472
+ lxw_xml_empty_tag(self->file, "c:radarStyle", &attributes);
473
+
474
+ LXW_FREE_ATTRIBUTES();
475
+ }
476
+
477
+ /*
478
+ * Write the <c:varyColors> element.
479
+ */
480
+ STATIC void
481
+ _chart_write_vary_colors(lxw_chart *self)
482
+ {
483
+ struct xml_attribute_list attributes;
484
+ struct xml_attribute *attribute;
485
+
486
+ LXW_INIT_ATTRIBUTES();
487
+ LXW_PUSH_ATTRIBUTES_STR("val", "1");
488
+
489
+ lxw_xml_empty_tag(self->file, "c:varyColors", &attributes);
490
+
491
+ LXW_FREE_ATTRIBUTES();
492
+ }
493
+
494
+ /*
495
+ * Write the <c:firstSliceAng> element.
496
+ */
497
+ STATIC void
498
+ _chart_write_first_slice_ang(lxw_chart *self)
499
+ {
500
+ struct xml_attribute_list attributes;
501
+ struct xml_attribute *attribute;
502
+
503
+ LXW_INIT_ATTRIBUTES();
504
+ LXW_PUSH_ATTRIBUTES_INT("val", self->rotation);
505
+
506
+ lxw_xml_empty_tag(self->file, "c:firstSliceAng", &attributes);
507
+
508
+ LXW_FREE_ATTRIBUTES();
509
+ }
510
+
511
+ /*
512
+ * Write the <c:holeSize> element.
513
+ */
514
+ STATIC void
515
+ _chart_write_hole_size(lxw_chart *self)
516
+ {
517
+ struct xml_attribute_list attributes;
518
+ struct xml_attribute *attribute;
519
+
520
+ LXW_INIT_ATTRIBUTES();
521
+ LXW_PUSH_ATTRIBUTES_INT("val", self->hole_size);
522
+
523
+ lxw_xml_empty_tag(self->file, "c:holeSize", &attributes);
524
+
525
+ LXW_FREE_ATTRIBUTES();
526
+ }
527
+
528
+ /*
529
+ * Write the <a:alpha> element.
530
+ */
531
+ STATIC void
532
+ _chart_write_a_alpha(lxw_chart *self, uint8_t transparency)
533
+ {
534
+ struct xml_attribute_list attributes;
535
+ struct xml_attribute *attribute;
536
+ uint32_t val;
537
+
538
+ LXW_INIT_ATTRIBUTES();
539
+
540
+ val = (100 - transparency) * 1000;
541
+
542
+ LXW_PUSH_ATTRIBUTES_INT("val", val);
543
+
544
+ lxw_xml_empty_tag(self->file, "a:alpha", &attributes);
545
+
546
+ LXW_FREE_ATTRIBUTES();
547
+ }
548
+
549
+ /*
550
+ * Write the <a:srgbClr> element.
551
+ */
552
+ STATIC void
553
+ _chart_write_a_srgb_clr(lxw_chart *self, lxw_color_t color,
554
+ uint8_t transparency)
555
+ {
556
+ struct xml_attribute_list attributes;
557
+ struct xml_attribute *attribute;
558
+ char rgb_str[LXW_ATTR_32];
559
+
560
+ LXW_INIT_ATTRIBUTES();
561
+
562
+ lxw_snprintf(rgb_str, LXW_ATTR_32, "%06X", color & LXW_COLOR_MASK);
563
+ LXW_PUSH_ATTRIBUTES_STR("val", rgb_str);
564
+
565
+ if (transparency) {
566
+ lxw_xml_start_tag(self->file, "a:srgbClr", &attributes);
567
+
568
+ /* Write the a:alpha element. */
569
+ _chart_write_a_alpha(self, transparency);
570
+
571
+ lxw_xml_end_tag(self->file, "a:srgbClr");
572
+ }
573
+ else {
574
+ lxw_xml_empty_tag(self->file, "a:srgbClr", &attributes);
575
+ }
576
+
577
+ LXW_FREE_ATTRIBUTES();
578
+ }
579
+
580
+ /*
581
+ * Write the <a:solidFill> element.
582
+ */
583
+ STATIC void
584
+ _chart_write_a_solid_fill(lxw_chart *self, lxw_color_t color,
585
+ uint8_t transparency)
586
+ {
587
+
588
+ lxw_xml_start_tag(self->file, "a:solidFill", NULL);
589
+
590
+ /* Write the a:srgbClr element. */
591
+ _chart_write_a_srgb_clr(self, color, transparency);
592
+
593
+ lxw_xml_end_tag(self->file, "a:solidFill");
594
+ }
595
+
596
+ /*
597
+ * Write the <a:t> element.
598
+ */
599
+ STATIC void
600
+ _chart_write_a_t(lxw_chart *self, char *name)
601
+ {
602
+ lxw_xml_data_element(self->file, "a:t", name, NULL);
603
+ }
604
+
605
+ /*
606
+ * Write the <a:endParaRPr> element.
607
+ */
608
+ STATIC void
609
+ _chart_write_a_end_para_rpr(lxw_chart *self)
610
+ {
611
+ struct xml_attribute_list attributes;
612
+ struct xml_attribute *attribute;
613
+
614
+ LXW_INIT_ATTRIBUTES();
615
+ LXW_PUSH_ATTRIBUTES_STR("lang", "en-US");
616
+
617
+ lxw_xml_empty_tag(self->file, "a:endParaRPr", &attributes);
618
+
619
+ LXW_FREE_ATTRIBUTES();
620
+ }
621
+
622
+ /*
623
+ * Write the <a:defRPr> element.
624
+ */
625
+ STATIC void
626
+ _chart_write_a_def_rpr(lxw_chart *self, lxw_chart_font *font)
627
+ {
628
+ struct xml_attribute_list attributes;
629
+ struct xml_attribute *attribute;
630
+ uint8_t has_color = LXW_FALSE;
631
+ uint8_t has_latin = LXW_FALSE;
632
+ uint8_t use_font_default = LXW_FALSE;
633
+
634
+ LXW_INIT_ATTRIBUTES();
635
+
636
+ if (font) {
637
+ has_color = font->color || font->has_color;
638
+ has_latin = font->name || font->pitch_family || font->charset;
639
+ use_font_default = !(has_color || has_latin || font->baseline == -1);
640
+
641
+ /* Set the font attributes. */
642
+ if (font->size)
643
+ LXW_PUSH_ATTRIBUTES_INT("sz", font->size);
644
+
645
+ if (use_font_default || font->bold)
646
+ LXW_PUSH_ATTRIBUTES_INT("b", font->bold & 0x1);
647
+
648
+ if (use_font_default || font->italic)
649
+ LXW_PUSH_ATTRIBUTES_INT("i", font->italic & 0x1);
650
+
651
+ if (font->underline)
652
+ LXW_PUSH_ATTRIBUTES_STR("u", "sng");
653
+
654
+ if (font->baseline != -1)
655
+ LXW_PUSH_ATTRIBUTES_INT("baseline", font->baseline);
656
+ }
657
+
658
+ /* There are sub-elements if the font name or color have changed. */
659
+ if (has_latin || has_color) {
660
+
661
+ lxw_xml_start_tag(self->file, "a:defRPr", &attributes);
662
+
663
+ if (has_color) {
664
+ _chart_write_a_solid_fill(self, font->color, LXW_FALSE);
665
+ }
666
+
667
+ if (has_latin) {
668
+ /* Free and reuse the attribute list for the latin attributes. */
669
+ LXW_FREE_ATTRIBUTES();
670
+
671
+ if (font->name)
672
+ LXW_PUSH_ATTRIBUTES_STR("typeface", font->name);
673
+
674
+ if (font->pitch_family)
675
+ LXW_PUSH_ATTRIBUTES_INT("pitchFamily", font->pitch_family);
676
+
677
+ if (font->pitch_family || font->charset)
678
+ LXW_PUSH_ATTRIBUTES_INT("charset", font->charset);
679
+
680
+ /* Write the <a:latin> element. */
681
+ lxw_xml_empty_tag(self->file, "a:latin", &attributes);
682
+ }
683
+
684
+ lxw_xml_end_tag(self->file, "a:defRPr");
685
+ }
686
+ else {
687
+ lxw_xml_empty_tag(self->file, "a:defRPr", &attributes);
688
+ }
689
+
690
+ LXW_FREE_ATTRIBUTES();
691
+ }
692
+
693
+ /*
694
+ * Write the <a:rPr> element.
695
+ */
696
+ STATIC void
697
+ _chart_write_a_r_pr(lxw_chart *self, lxw_chart_font *font)
698
+ {
699
+ struct xml_attribute_list attributes;
700
+ struct xml_attribute *attribute;
701
+ uint8_t has_color = LXW_FALSE;
702
+ uint8_t has_latin = LXW_FALSE;
703
+ uint8_t use_font_default = LXW_FALSE;
704
+
705
+ LXW_INIT_ATTRIBUTES();
706
+ LXW_PUSH_ATTRIBUTES_STR("lang", "en-US");
707
+
708
+ if (font) {
709
+ has_color = font->color || font->has_color;
710
+ has_latin = font->name || font->pitch_family || font->charset;
711
+ use_font_default = !(has_color || has_latin || font->baseline == -1);
712
+
713
+ /* Set the font attributes. */
714
+ if (font->size)
715
+ LXW_PUSH_ATTRIBUTES_INT("sz", font->size);
716
+
717
+ if (use_font_default || font->bold)
718
+ LXW_PUSH_ATTRIBUTES_INT("b", font->bold & 0x1);
719
+
720
+ if (use_font_default || font->italic)
721
+ LXW_PUSH_ATTRIBUTES_INT("i", font->italic & 0x1);
722
+
723
+ if (font->underline)
724
+ LXW_PUSH_ATTRIBUTES_STR("u", "sng");
725
+
726
+ if (font->baseline != -1)
727
+ LXW_PUSH_ATTRIBUTES_INT("baseline", font->baseline);
728
+ }
729
+
730
+ /* There are sub-elements if the font name or color have changed. */
731
+ if (has_latin || has_color) {
732
+
733
+ lxw_xml_start_tag(self->file, "a:rPr", &attributes);
734
+
735
+ if (has_color) {
736
+ _chart_write_a_solid_fill(self, font->color, LXW_FALSE);
737
+ }
738
+
739
+ if (has_latin) {
740
+ /* Free and reuse the attribute list for the latin attributes. */
741
+ LXW_FREE_ATTRIBUTES();
742
+
743
+ if (font->name)
744
+ LXW_PUSH_ATTRIBUTES_STR("typeface", font->name);
745
+
746
+ if (font->pitch_family)
747
+ LXW_PUSH_ATTRIBUTES_INT("pitchFamily", font->pitch_family);
748
+
749
+ if (font->pitch_family || font->charset)
750
+ LXW_PUSH_ATTRIBUTES_INT("charset", font->charset);
751
+
752
+ /* Write the <a:latin> element. */
753
+ lxw_xml_empty_tag(self->file, "a:latin", &attributes);
754
+ }
755
+
756
+ lxw_xml_end_tag(self->file, "a:rPr");
757
+ }
758
+ else {
759
+ lxw_xml_empty_tag(self->file, "a:rPr", &attributes);
760
+ }
761
+
762
+ LXW_FREE_ATTRIBUTES();
763
+ }
764
+
765
+ /*
766
+ * Write the <a:r> element.
767
+ */
768
+ STATIC void
769
+ _chart_write_a_r(lxw_chart *self, char *name, lxw_chart_font *font)
770
+ {
771
+ lxw_xml_start_tag(self->file, "a:r", NULL);
772
+
773
+ /* Write the a:rPr element. */
774
+ _chart_write_a_r_pr(self, font);
775
+
776
+ /* Write the a:t element. */
777
+ _chart_write_a_t(self, name);
778
+
779
+ lxw_xml_end_tag(self->file, "a:r");
780
+ }
781
+
782
+ /*
783
+ * Write the <a:pPr> element.
784
+ */
785
+ STATIC void
786
+ _chart_write_a_p_pr_formula(lxw_chart *self, lxw_chart_font *font)
787
+ {
788
+ lxw_xml_start_tag(self->file, "a:pPr", NULL);
789
+
790
+ /* Write the a:defRPr element. */
791
+ _chart_write_a_def_rpr(self, font);
792
+
793
+ lxw_xml_end_tag(self->file, "a:pPr");
794
+ }
795
+
796
+ /*
797
+ * Write the <a:pPr> element for pie chart legends.
798
+ */
799
+ STATIC void
800
+ _chart_write_a_p_pr_pie(lxw_chart *self, lxw_chart_font *font)
801
+ {
802
+ struct xml_attribute_list attributes;
803
+ struct xml_attribute *attribute;
804
+
805
+ LXW_INIT_ATTRIBUTES();
806
+ LXW_PUSH_ATTRIBUTES_STR("rtl", "0");
807
+
808
+ lxw_xml_start_tag(self->file, "a:pPr", &attributes);
809
+
810
+ /* Write the a:defRPr element. */
811
+ _chart_write_a_def_rpr(self, font);
812
+
813
+ lxw_xml_end_tag(self->file, "a:pPr");
814
+
815
+ LXW_FREE_ATTRIBUTES();
816
+ }
817
+
818
+ /*
819
+ * Write the <a:pPr> element.
820
+ */
821
+ STATIC void
822
+ _chart_write_a_p_pr_rich(lxw_chart *self, lxw_chart_font *font)
823
+ {
824
+ lxw_xml_start_tag(self->file, "a:pPr", NULL);
825
+
826
+ /* Write the a:defRPr element. */
827
+ _chart_write_a_def_rpr(self, font);
828
+
829
+ lxw_xml_end_tag(self->file, "a:pPr");
830
+ }
831
+
832
+ /*
833
+ * Write the <a:p> element.
834
+ */
835
+ STATIC void
836
+ _chart_write_a_p_formula(lxw_chart *self, lxw_chart_font *font)
837
+ {
838
+ lxw_xml_start_tag(self->file, "a:p", NULL);
839
+
840
+ /* Write the a:pPr element. */
841
+ _chart_write_a_p_pr_formula(self, font);
842
+
843
+ /* Write the a:endParaRPr element. */
844
+ _chart_write_a_end_para_rpr(self);
845
+
846
+ lxw_xml_end_tag(self->file, "a:p");
847
+ }
848
+
849
+ /*
850
+ * Write the <a:p> element for pie chart legends.
851
+ */
852
+ STATIC void
853
+ _chart_write_a_p_pie(lxw_chart *self, lxw_chart_font *font)
854
+ {
855
+ lxw_xml_start_tag(self->file, "a:p", NULL);
856
+
857
+ /* Write the a:pPr element. */
858
+ _chart_write_a_p_pr_pie(self, font);
859
+
860
+ /* Write the a:endParaRPr element. */
861
+ _chart_write_a_end_para_rpr(self);
862
+
863
+ lxw_xml_end_tag(self->file, "a:p");
864
+ }
865
+
866
+ /*
867
+ * Write the <a:p> element.
868
+ */
869
+ STATIC void
870
+ _chart_write_a_p_rich(lxw_chart *self, char *name, lxw_chart_font *font)
871
+ {
872
+ lxw_xml_start_tag(self->file, "a:p", NULL);
873
+
874
+ /* Write the a:pPr element. */
875
+ _chart_write_a_p_pr_rich(self, font);
876
+
877
+ /* Write the a:r element. */
878
+ _chart_write_a_r(self, name, font);
879
+
880
+ lxw_xml_end_tag(self->file, "a:p");
881
+ }
882
+
883
+ /*
884
+ * Write the <a:lstStyle> element.
885
+ */
886
+ STATIC void
887
+ _chart_write_a_lst_style(lxw_chart *self)
888
+ {
889
+ lxw_xml_empty_tag(self->file, "a:lstStyle", NULL);
890
+ }
891
+
892
+ /*
893
+ * Write the <a:bodyPr> element.
894
+ */
895
+ STATIC void
896
+ _chart_write_a_body_pr(lxw_chart *self, int32_t rotation,
897
+ uint8_t is_horizontal)
898
+ {
899
+ struct xml_attribute_list attributes;
900
+ struct xml_attribute *attribute;
901
+
902
+ LXW_INIT_ATTRIBUTES();
903
+
904
+ if (rotation == 0 && is_horizontal)
905
+ rotation = -5400000;
906
+
907
+ if (rotation)
908
+ LXW_PUSH_ATTRIBUTES_INT("rot", rotation);
909
+
910
+ if (is_horizontal)
911
+ LXW_PUSH_ATTRIBUTES_STR("vert", "horz");
912
+
913
+ lxw_xml_empty_tag(self->file, "a:bodyPr", &attributes);
914
+
915
+ LXW_FREE_ATTRIBUTES();
916
+ }
917
+
918
+ /*
919
+ * Write the <c:ptCount> element.
920
+ */
921
+ STATIC void
922
+ _chart_write_pt_count(lxw_chart *self, uint16_t num_data_points)
923
+ {
924
+ struct xml_attribute_list attributes;
925
+ struct xml_attribute *attribute;
926
+
927
+ LXW_INIT_ATTRIBUTES();
928
+ LXW_PUSH_ATTRIBUTES_INT("val", num_data_points);
929
+
930
+ lxw_xml_empty_tag(self->file, "c:ptCount", &attributes);
931
+
932
+ LXW_FREE_ATTRIBUTES();
933
+ }
934
+
935
+ /*
936
+ * Write the <c:v> element.
937
+ */
938
+ STATIC void
939
+ _chart_write_v_num(lxw_chart *self, double number)
940
+ {
941
+ char data[LXW_ATTR_32];
942
+
943
+ lxw_snprintf(data, LXW_ATTR_32, "%.16g", number);
944
+
945
+ lxw_xml_data_element(self->file, "c:v", data, NULL);
946
+ }
947
+
948
+ /*
949
+ * Write the <c:v> element.
950
+ */
951
+ STATIC void
952
+ _chart_write_v_str(lxw_chart *self, char *str)
953
+ {
954
+ lxw_xml_data_element(self->file, "c:v", str, NULL);
955
+ }
956
+
957
+ /*
958
+ * Write the <c:f> element.
959
+ */
960
+ STATIC void
961
+ _chart_write_f(lxw_chart *self, char *formula)
962
+ {
963
+ lxw_xml_data_element(self->file, "c:f", formula, NULL);
964
+ }
965
+
966
+ /*
967
+ * Write the <c:pt> element.
968
+ */
969
+ STATIC void
970
+ _chart_write_pt(lxw_chart *self, uint16_t index,
971
+ lxw_series_data_point *data_point)
972
+ {
973
+ struct xml_attribute_list attributes;
974
+ struct xml_attribute *attribute;
975
+
976
+ /* Ignore chart points that have no data. */
977
+ if (data_point->no_data)
978
+ return;
979
+
980
+ LXW_INIT_ATTRIBUTES();
981
+ LXW_PUSH_ATTRIBUTES_INT("idx", index);
982
+
983
+ lxw_xml_start_tag(self->file, "c:pt", &attributes);
984
+
985
+ if (data_point->is_string && data_point->string)
986
+ _chart_write_v_str(self, data_point->string);
987
+ else
988
+ _chart_write_v_num(self, data_point->number);
989
+
990
+ lxw_xml_end_tag(self->file, "c:pt");
991
+
992
+ LXW_FREE_ATTRIBUTES();
993
+ }
994
+
995
+ /*
996
+ * Write the <c:pt> element.
997
+ */
998
+ STATIC void
999
+ _chart_write_num_pt(lxw_chart *self, uint16_t index,
1000
+ lxw_series_data_point *data_point)
1001
+ {
1002
+ struct xml_attribute_list attributes;
1003
+ struct xml_attribute *attribute;
1004
+
1005
+ /* Ignore chart points that have no data. */
1006
+ if (data_point->no_data)
1007
+ return;
1008
+
1009
+ LXW_INIT_ATTRIBUTES();
1010
+ LXW_PUSH_ATTRIBUTES_INT("idx", index);
1011
+
1012
+ lxw_xml_start_tag(self->file, "c:pt", &attributes);
1013
+
1014
+ _chart_write_v_num(self, data_point->number);
1015
+
1016
+ lxw_xml_end_tag(self->file, "c:pt");
1017
+
1018
+ LXW_FREE_ATTRIBUTES();
1019
+ }
1020
+
1021
+ /*
1022
+ * Write the <c:formatCode> element.
1023
+ */
1024
+ STATIC void
1025
+ _chart_write_format_code(lxw_chart *self)
1026
+ {
1027
+ lxw_xml_data_element(self->file, "c:formatCode", "General", NULL);
1028
+ }
1029
+
1030
+ /*
1031
+ * Write the <c:numCache> element.
1032
+ */
1033
+ STATIC void
1034
+ _chart_write_num_cache(lxw_chart *self, lxw_series_range *range)
1035
+ {
1036
+ lxw_series_data_point *data_point;
1037
+ uint16_t index = 0;
1038
+
1039
+ lxw_xml_start_tag(self->file, "c:numCache", NULL);
1040
+
1041
+ /* Write the c:formatCode element. */
1042
+ _chart_write_format_code(self);
1043
+
1044
+ /* Write the c:ptCount element. */
1045
+ _chart_write_pt_count(self, range->num_data_points);
1046
+
1047
+ STAILQ_FOREACH(data_point, range->data_cache, list_pointers) {
1048
+ /* Write the c:pt element. */
1049
+ _chart_write_num_pt(self, index, data_point);
1050
+ index++;
1051
+ }
1052
+
1053
+ lxw_xml_end_tag(self->file, "c:numCache");
1054
+ }
1055
+
1056
+ /*
1057
+ * Write the <c:strCache> element.
1058
+ */
1059
+ STATIC void
1060
+ _chart_write_str_cache(lxw_chart *self, lxw_series_range *range)
1061
+ {
1062
+ lxw_series_data_point *data_point;
1063
+ uint16_t index = 0;
1064
+
1065
+ lxw_xml_start_tag(self->file, "c:strCache", NULL);
1066
+
1067
+ /* Write the c:ptCount element. */
1068
+ _chart_write_pt_count(self, range->num_data_points);
1069
+
1070
+ STAILQ_FOREACH(data_point, range->data_cache, list_pointers) {
1071
+ /* Write the c:pt element. */
1072
+ _chart_write_pt(self, index, data_point);
1073
+ index++;
1074
+ }
1075
+
1076
+ lxw_xml_end_tag(self->file, "c:strCache");
1077
+ }
1078
+
1079
+ /*
1080
+ * Write the <c:numRef> element.
1081
+ */
1082
+ STATIC void
1083
+ _chart_write_num_ref(lxw_chart *self, lxw_series_range *range)
1084
+ {
1085
+ lxw_xml_start_tag(self->file, "c:numRef", NULL);
1086
+
1087
+ /* Write the c:f element. */
1088
+ _chart_write_f(self, range->formula);
1089
+
1090
+ if (!STAILQ_EMPTY(range->data_cache)) {
1091
+ /* Write the c:numCache element. */
1092
+ _chart_write_num_cache(self, range);
1093
+ }
1094
+
1095
+ lxw_xml_end_tag(self->file, "c:numRef");
1096
+ }
1097
+
1098
+ /*
1099
+ * Write the <c:strRef> element.
1100
+ */
1101
+ STATIC void
1102
+ _chart_write_str_ref(lxw_chart *self, lxw_series_range *range)
1103
+ {
1104
+ lxw_xml_start_tag(self->file, "c:strRef", NULL);
1105
+
1106
+ /* Write the c:f element. */
1107
+ _chart_write_f(self, range->formula);
1108
+
1109
+ if (!STAILQ_EMPTY(range->data_cache)) {
1110
+ /* Write the c:strCache element. */
1111
+ _chart_write_str_cache(self, range);
1112
+ }
1113
+
1114
+ lxw_xml_end_tag(self->file, "c:strRef");
1115
+ }
1116
+
1117
+ /*
1118
+ * Write the cached data elements.
1119
+ */
1120
+ STATIC void
1121
+ _chart_write_data_cache(lxw_chart *self, lxw_series_range *range,
1122
+ uint8_t has_string_cache)
1123
+ {
1124
+ if (has_string_cache) {
1125
+ /* Write the c:strRef element. */
1126
+ _chart_write_str_ref(self, range);
1127
+ }
1128
+ else {
1129
+ /* Write the c:numRef element. */
1130
+ _chart_write_num_ref(self, range);
1131
+ }
1132
+ }
1133
+
1134
+ /*
1135
+ * Write the <c:tx> element with a simple value such as for series names.
1136
+ */
1137
+ STATIC void
1138
+ _chart_write_tx_value(lxw_chart *self, char *name)
1139
+ {
1140
+ lxw_xml_start_tag(self->file, "c:tx", NULL);
1141
+
1142
+ /* Write the c:v element. */
1143
+ _chart_write_v_str(self, name);
1144
+
1145
+ lxw_xml_end_tag(self->file, "c:tx");
1146
+ }
1147
+
1148
+ /*
1149
+ * Write the <c:tx> element with a simple value such as for series names.
1150
+ */
1151
+ STATIC void
1152
+ _chart_write_tx_formula(lxw_chart *self, lxw_chart_title *title)
1153
+ {
1154
+ lxw_xml_start_tag(self->file, "c:tx", NULL);
1155
+
1156
+ _chart_write_str_ref(self, title->range);
1157
+
1158
+ lxw_xml_end_tag(self->file, "c:tx");
1159
+ }
1160
+
1161
+ /*
1162
+ * Write the <c:txPr> element.
1163
+ */
1164
+ STATIC void
1165
+ _chart_write_tx_pr(lxw_chart *self, uint8_t is_horizontal,
1166
+ lxw_chart_font *font)
1167
+ {
1168
+ int32_t rotation = 0;
1169
+
1170
+ if (font)
1171
+ rotation = font->rotation;
1172
+
1173
+ lxw_xml_start_tag(self->file, "c:txPr", NULL);
1174
+
1175
+ /* Write the a:bodyPr element. */
1176
+ _chart_write_a_body_pr(self, rotation, is_horizontal);
1177
+
1178
+ /* Write the a:lstStyle element. */
1179
+ _chart_write_a_lst_style(self);
1180
+
1181
+ /* Write the a:p element. */
1182
+ _chart_write_a_p_formula(self, font);
1183
+
1184
+ lxw_xml_end_tag(self->file, "c:txPr");
1185
+ }
1186
+
1187
+ /*
1188
+ * Write the <c:txPr> element for pie chart legends.
1189
+ */
1190
+ STATIC void
1191
+ _chart_write_tx_pr_pie(lxw_chart *self, uint8_t is_horizontal,
1192
+ lxw_chart_font *font)
1193
+ {
1194
+ int32_t rotation = 0;
1195
+
1196
+ if (font)
1197
+ rotation = font->rotation;
1198
+
1199
+ lxw_xml_start_tag(self->file, "c:txPr", NULL);
1200
+
1201
+ /* Write the a:bodyPr element. */
1202
+ _chart_write_a_body_pr(self, rotation, is_horizontal);
1203
+
1204
+ /* Write the a:lstStyle element. */
1205
+ _chart_write_a_lst_style(self);
1206
+
1207
+ /* Write the a:p element. */
1208
+ _chart_write_a_p_pie(self, font);
1209
+
1210
+ lxw_xml_end_tag(self->file, "c:txPr");
1211
+ }
1212
+
1213
+ /*
1214
+ * Write the <c:txPr> element.
1215
+ */
1216
+ STATIC void
1217
+ _chart_write_axis_font(lxw_chart *self, lxw_chart_font *font)
1218
+ {
1219
+ if (!font)
1220
+ return;
1221
+
1222
+ lxw_xml_start_tag(self->file, "c:txPr", NULL);
1223
+
1224
+ /* Write the a:bodyPr element. */
1225
+ _chart_write_a_body_pr(self, font->rotation, LXW_FALSE);
1226
+
1227
+ /* Write the a:lstStyle element. */
1228
+ _chart_write_a_lst_style(self);
1229
+
1230
+ lxw_xml_start_tag(self->file, "a:p", NULL);
1231
+
1232
+ /* Write the a:pPr element. */
1233
+ _chart_write_a_p_pr_rich(self, font);
1234
+
1235
+ /* Write the a:endParaRPr element. */
1236
+ _chart_write_a_end_para_rpr(self);
1237
+
1238
+ lxw_xml_end_tag(self->file, "a:p");
1239
+ lxw_xml_end_tag(self->file, "c:txPr");
1240
+ }
1241
+
1242
+ /*
1243
+ * Write the <c:rich> element.
1244
+ */
1245
+ STATIC void
1246
+ _chart_write_rich(lxw_chart *self, char *name, uint8_t is_horizontal,
1247
+ lxw_chart_font *font)
1248
+ {
1249
+ int32_t rotation = 0;
1250
+
1251
+ if (font)
1252
+ rotation = font->rotation;
1253
+
1254
+ lxw_xml_start_tag(self->file, "c:rich", NULL);
1255
+
1256
+ /* Write the a:bodyPr element. */
1257
+ _chart_write_a_body_pr(self, rotation, is_horizontal);
1258
+
1259
+ /* Write the a:lstStyle element. */
1260
+ _chart_write_a_lst_style(self);
1261
+
1262
+ /* Write the a:p element. */
1263
+ _chart_write_a_p_rich(self, name, font);
1264
+
1265
+ lxw_xml_end_tag(self->file, "c:rich");
1266
+ }
1267
+
1268
+ /*
1269
+ * Write the <c:tx> element.
1270
+ */
1271
+ STATIC void
1272
+ _chart_write_tx_rich(lxw_chart *self, char *name, uint8_t is_horizontal,
1273
+ lxw_chart_font *font)
1274
+ {
1275
+
1276
+ lxw_xml_start_tag(self->file, "c:tx", NULL);
1277
+
1278
+ /* Write the c:rich element. */
1279
+ _chart_write_rich(self, name, is_horizontal, font);
1280
+
1281
+ lxw_xml_end_tag(self->file, "c:tx");
1282
+ }
1283
+
1284
+ /*
1285
+ * Write the <c:title> element for rich strings.
1286
+ */
1287
+ STATIC void
1288
+ _chart_write_title_rich(lxw_chart *self, lxw_chart_title *title)
1289
+ {
1290
+ lxw_xml_start_tag(self->file, "c:title", NULL);
1291
+
1292
+ /* Write the c:tx element. */
1293
+ _chart_write_tx_rich(self, title->name, title->is_horizontal,
1294
+ title->font);
1295
+
1296
+ /* Write the c:layout element. */
1297
+ _chart_write_layout(self);
1298
+
1299
+ lxw_xml_end_tag(self->file, "c:title");
1300
+ }
1301
+
1302
+ /*
1303
+ * Write the <c:title> element for a formula style title
1304
+ */
1305
+ STATIC void
1306
+ _chart_write_title_formula(lxw_chart *self, lxw_chart_title *title)
1307
+ {
1308
+ lxw_xml_start_tag(self->file, "c:title", NULL);
1309
+
1310
+ /* Write the c:tx element. */
1311
+ _chart_write_tx_formula(self, title);
1312
+
1313
+ /* Write the c:layout element. */
1314
+ _chart_write_layout(self);
1315
+
1316
+ /* Write the c:txPr element. */
1317
+ _chart_write_tx_pr(self, title->is_horizontal, title->font);
1318
+
1319
+ lxw_xml_end_tag(self->file, "c:title");
1320
+ }
1321
+
1322
+ /*
1323
+ * Write the <c:delete> element.
1324
+ */
1325
+ STATIC void
1326
+ _chart_write_delete(lxw_chart *self)
1327
+ {
1328
+ struct xml_attribute_list attributes;
1329
+ struct xml_attribute *attribute;
1330
+
1331
+ LXW_INIT_ATTRIBUTES();
1332
+ LXW_PUSH_ATTRIBUTES_STR("val", "1");
1333
+
1334
+ lxw_xml_empty_tag(self->file, "c:delete", &attributes);
1335
+
1336
+ LXW_FREE_ATTRIBUTES();
1337
+ }
1338
+
1339
+ /*
1340
+ * Write the <c:autoTitleDeleted> element.
1341
+ */
1342
+ STATIC void
1343
+ _chart_write_auto_title_deleted(lxw_chart *self)
1344
+ {
1345
+ struct xml_attribute_list attributes;
1346
+ struct xml_attribute *attribute;
1347
+
1348
+ LXW_INIT_ATTRIBUTES();
1349
+ LXW_PUSH_ATTRIBUTES_STR("val", "1");
1350
+
1351
+ lxw_xml_empty_tag(self->file, "c:autoTitleDeleted", &attributes);
1352
+
1353
+ LXW_FREE_ATTRIBUTES();
1354
+ }
1355
+
1356
+ /*
1357
+ * Write the <c:idx> element.
1358
+ */
1359
+ STATIC void
1360
+ _chart_write_idx(lxw_chart *self, uint16_t index)
1361
+ {
1362
+ struct xml_attribute_list attributes;
1363
+ struct xml_attribute *attribute;
1364
+
1365
+ LXW_INIT_ATTRIBUTES();
1366
+ LXW_PUSH_ATTRIBUTES_INT("val", index);
1367
+
1368
+ lxw_xml_empty_tag(self->file, "c:idx", &attributes);
1369
+
1370
+ LXW_FREE_ATTRIBUTES();
1371
+ }
1372
+
1373
+ /*
1374
+ * Write the <a:prstDash> element.
1375
+ */
1376
+ STATIC void
1377
+ _chart_write_a_prst_dash(lxw_chart *self, uint8_t dash_type)
1378
+ {
1379
+ struct xml_attribute_list attributes;
1380
+ struct xml_attribute *attribute;
1381
+
1382
+ LXW_INIT_ATTRIBUTES();
1383
+
1384
+ if (dash_type == LXW_CHART_LINE_DASH_ROUND_DOT)
1385
+ LXW_PUSH_ATTRIBUTES_STR("val", "sysDot");
1386
+ else if (dash_type == LXW_CHART_LINE_DASH_SQUARE_DOT)
1387
+ LXW_PUSH_ATTRIBUTES_STR("val", "sysDash");
1388
+ else if (dash_type == LXW_CHART_LINE_DASH_DASH_DOT)
1389
+ LXW_PUSH_ATTRIBUTES_STR("val", "dashDot");
1390
+ else if (dash_type == LXW_CHART_LINE_DASH_LONG_DASH)
1391
+ LXW_PUSH_ATTRIBUTES_STR("val", "lgDash");
1392
+ else if (dash_type == LXW_CHART_LINE_DASH_LONG_DASH_DOT)
1393
+ LXW_PUSH_ATTRIBUTES_STR("val", "lgDashDot");
1394
+ else if (dash_type == LXW_CHART_LINE_DASH_LONG_DASH_DOT_DOT)
1395
+ LXW_PUSH_ATTRIBUTES_STR("val", "lgDashDotDot");
1396
+ else if (dash_type == LXW_CHART_LINE_DASH_DOT)
1397
+ LXW_PUSH_ATTRIBUTES_STR("val", "dot");
1398
+ else if (dash_type == LXW_CHART_LINE_DASH_SYSTEM_DASH_DOT)
1399
+ LXW_PUSH_ATTRIBUTES_STR("val", "sysDashDot");
1400
+ else if (dash_type == LXW_CHART_LINE_DASH_SYSTEM_DASH_DOT_DOT)
1401
+ LXW_PUSH_ATTRIBUTES_STR("val", "sysDashDotDot");
1402
+ else
1403
+ LXW_PUSH_ATTRIBUTES_STR("val", "dash");
1404
+
1405
+ lxw_xml_empty_tag(self->file, "a:prstDash", &attributes);
1406
+
1407
+ LXW_FREE_ATTRIBUTES();
1408
+ }
1409
+
1410
+ /*
1411
+ * Write the <a:noFill> element.
1412
+ */
1413
+ STATIC void
1414
+ _chart_write_a_no_fill(lxw_chart *self)
1415
+ {
1416
+ lxw_xml_empty_tag(self->file, "a:noFill", NULL);
1417
+ }
1418
+
1419
+ /*
1420
+ * Write the <a:ln> element.
1421
+ */
1422
+ STATIC void
1423
+ _chart_write_a_ln(lxw_chart *self, lxw_chart_line *line)
1424
+ {
1425
+ struct xml_attribute_list attributes;
1426
+ struct xml_attribute *attribute;
1427
+ float width_flt = line->width;
1428
+ uint32_t width_int;
1429
+
1430
+ LXW_INIT_ATTRIBUTES();
1431
+
1432
+ /* Round width to nearest 0.25, like Excel. */
1433
+ width_flt = (float) (uint32_t) ((line->width + 0.125) * 4.0) / 4.0;
1434
+
1435
+ /* Convert to internal units. */
1436
+ width_int = (uint32_t) (0.5 + (12700.0 * width_flt));
1437
+
1438
+ if (width_int)
1439
+ LXW_PUSH_ATTRIBUTES_INT("w", width_int);
1440
+
1441
+ lxw_xml_start_tag(self->file, "a:ln", &attributes);
1442
+
1443
+ /* Write the line fill. */
1444
+ if (line->none) {
1445
+ /* Write the a:noFill element. */
1446
+ _chart_write_a_no_fill(self);
1447
+ }
1448
+ else if (line->has_color) {
1449
+ /* Write the a:solidFill element. */
1450
+ _chart_write_a_solid_fill(self, line->color, line->transparency);
1451
+ }
1452
+
1453
+ /* Write the line/dash type. */
1454
+ if (line->dash_type) {
1455
+ /* Write the a:prstDash element. */
1456
+ _chart_write_a_prst_dash(self, line->dash_type);
1457
+ }
1458
+
1459
+ lxw_xml_end_tag(self->file, "a:ln");
1460
+
1461
+ LXW_FREE_ATTRIBUTES();
1462
+ }
1463
+
1464
+ /*
1465
+ * Write the <c:spPr> element.
1466
+ */
1467
+ STATIC void
1468
+ _chart_write_sp_pr(lxw_chart *self, lxw_chart_line *line,
1469
+ lxw_chart_fill *fill)
1470
+ {
1471
+ if (!line && !fill)
1472
+ return;
1473
+
1474
+ lxw_xml_start_tag(self->file, "c:spPr", NULL);
1475
+
1476
+ /* Write the series fill. */
1477
+ if (fill) {
1478
+ if (fill->none) {
1479
+ /* Write the a:noFill element. */
1480
+ _chart_write_a_no_fill(self);
1481
+ }
1482
+ else {
1483
+ /* Write the a:solidFill element. */
1484
+ _chart_write_a_solid_fill(self, fill->color, fill->transparency);
1485
+ }
1486
+ }
1487
+
1488
+ if (line) {
1489
+ /* Write the a:ln element. */
1490
+ _chart_write_a_ln(self, line);
1491
+ }
1492
+
1493
+ lxw_xml_end_tag(self->file, "c:spPr");
1494
+ }
1495
+
1496
+ /*
1497
+ * Write the <c:order> element.
1498
+ */
1499
+ STATIC void
1500
+ _chart_write_order(lxw_chart *self, uint16_t index)
1501
+ {
1502
+ struct xml_attribute_list attributes;
1503
+ struct xml_attribute *attribute;
1504
+
1505
+ LXW_INIT_ATTRIBUTES();
1506
+ LXW_PUSH_ATTRIBUTES_INT("val", index);
1507
+
1508
+ lxw_xml_empty_tag(self->file, "c:order", &attributes);
1509
+
1510
+ LXW_FREE_ATTRIBUTES();
1511
+ }
1512
+
1513
+ /*
1514
+ * Write the <c:axId> element.
1515
+ */
1516
+ STATIC void
1517
+ _chart_write_axis_id(lxw_chart *self, uint32_t axis_id)
1518
+ {
1519
+ struct xml_attribute_list attributes;
1520
+ struct xml_attribute *attribute;
1521
+
1522
+ LXW_INIT_ATTRIBUTES();
1523
+ LXW_PUSH_ATTRIBUTES_INT("val", axis_id);
1524
+
1525
+ lxw_xml_empty_tag(self->file, "c:axId", &attributes);
1526
+
1527
+ LXW_FREE_ATTRIBUTES();
1528
+ }
1529
+
1530
+ /*
1531
+ * Write the <c:axId> element.
1532
+ */
1533
+ STATIC void
1534
+ _chart_write_axis_ids(lxw_chart *self)
1535
+ {
1536
+ if (!self->axis_id_1)
1537
+ _chart_add_axis_ids(self);
1538
+
1539
+ _chart_write_axis_id(self, self->axis_id_1);
1540
+ _chart_write_axis_id(self, self->axis_id_2);
1541
+ }
1542
+
1543
+ /*
1544
+ * Write the series name.
1545
+ */
1546
+ STATIC void
1547
+ _chart_write_series_name(lxw_chart *self, lxw_chart_series *series)
1548
+ {
1549
+ if (series->title.name) {
1550
+ /* Write the c:tx element. */
1551
+ _chart_write_tx_value(self, series->title.name);
1552
+ }
1553
+ else if (series->title.range->formula) {
1554
+ /* Write the c:tx element. */
1555
+ _chart_write_tx_formula(self, &series->title);
1556
+
1557
+ }
1558
+ }
1559
+
1560
+ /*
1561
+ * Write the <c:majorTickMark> element.
1562
+ */
1563
+ STATIC void
1564
+ _chart_write_major_tick_mark(lxw_chart *self, lxw_chart_axis *axis)
1565
+ {
1566
+ struct xml_attribute_list attributes;
1567
+ struct xml_attribute *attribute;
1568
+
1569
+ if (!axis->major_tick_mark)
1570
+ return;
1571
+
1572
+ LXW_INIT_ATTRIBUTES();
1573
+ LXW_PUSH_ATTRIBUTES_STR("val", "cross");
1574
+
1575
+ lxw_xml_empty_tag(self->file, "c:majorTickMark", &attributes);
1576
+
1577
+ LXW_FREE_ATTRIBUTES();
1578
+ }
1579
+
1580
+ /*
1581
+ * Write the <c:symbol> element.
1582
+ */
1583
+ STATIC void
1584
+ _chart_write_symbol(lxw_chart *self)
1585
+ {
1586
+ struct xml_attribute_list attributes;
1587
+ struct xml_attribute *attribute;
1588
+ char val[] = "none";
1589
+
1590
+ LXW_INIT_ATTRIBUTES();
1591
+ LXW_PUSH_ATTRIBUTES_STR("val", val);
1592
+
1593
+ lxw_xml_empty_tag(self->file, "c:symbol", &attributes);
1594
+
1595
+ LXW_FREE_ATTRIBUTES();
1596
+ }
1597
+
1598
+ /*
1599
+ * Write the <c:marker> element.
1600
+ */
1601
+ STATIC void
1602
+ _chart_write_marker(lxw_chart *self)
1603
+ {
1604
+ if (!self->has_markers)
1605
+ return;
1606
+
1607
+ lxw_xml_start_tag(self->file, "c:marker", NULL);
1608
+
1609
+ /* Write the c:symbol element. */
1610
+ _chart_write_symbol(self);
1611
+
1612
+ lxw_xml_end_tag(self->file, "c:marker");
1613
+ }
1614
+
1615
+ /*
1616
+ * Write the <c:marker> element.
1617
+ */
1618
+ STATIC void
1619
+ _chart_write_marker_value(lxw_chart *self)
1620
+ {
1621
+ struct xml_attribute_list attributes;
1622
+ struct xml_attribute *attribute;
1623
+ char val[] = "1";
1624
+
1625
+ LXW_INIT_ATTRIBUTES();
1626
+ LXW_PUSH_ATTRIBUTES_STR("val", val);
1627
+
1628
+ lxw_xml_empty_tag(self->file, "c:marker", &attributes);
1629
+
1630
+ LXW_FREE_ATTRIBUTES();
1631
+ }
1632
+
1633
+ /*
1634
+ * Write the <c:smooth> element.
1635
+ */
1636
+ STATIC void
1637
+ _chart_write_smooth(lxw_chart *self)
1638
+ {
1639
+ struct xml_attribute_list attributes;
1640
+ struct xml_attribute *attribute;
1641
+ char val[] = "1";
1642
+
1643
+ LXW_INIT_ATTRIBUTES();
1644
+ LXW_PUSH_ATTRIBUTES_STR("val", val);
1645
+
1646
+ lxw_xml_empty_tag(self->file, "c:smooth", &attributes);
1647
+
1648
+ LXW_FREE_ATTRIBUTES();
1649
+ }
1650
+
1651
+ /*
1652
+ * Write the <c:scatterStyle> element.
1653
+ */
1654
+ STATIC void
1655
+ _chart_write_scatter_style(lxw_chart *self)
1656
+ {
1657
+ struct xml_attribute_list attributes;
1658
+ struct xml_attribute *attribute;
1659
+
1660
+ LXW_INIT_ATTRIBUTES();
1661
+
1662
+ if (self->type == LXW_CHART_SCATTER_SMOOTH
1663
+ || self->type == LXW_CHART_SCATTER_SMOOTH_WITH_MARKERS)
1664
+ LXW_PUSH_ATTRIBUTES_STR("val", "smoothMarker");
1665
+ else
1666
+ LXW_PUSH_ATTRIBUTES_STR("val", "lineMarker");
1667
+
1668
+ lxw_xml_empty_tag(self->file, "c:scatterStyle", &attributes);
1669
+
1670
+ LXW_FREE_ATTRIBUTES();
1671
+ }
1672
+
1673
+ /*
1674
+ * Write the <c:cat> element.
1675
+ */
1676
+ STATIC void
1677
+ _chart_write_cat(lxw_chart *self, lxw_chart_series *series)
1678
+ {
1679
+ uint8_t has_string_cache = series->categories->has_string_cache;
1680
+
1681
+ /* Ignore <c:cat> elements for charts without category values. */
1682
+ if (!series->categories->formula)
1683
+ return;
1684
+
1685
+ self->cat_has_num_fmt = !has_string_cache;
1686
+
1687
+ lxw_xml_start_tag(self->file, "c:cat", NULL);
1688
+
1689
+ /* Write the c:numRef element. */
1690
+ _chart_write_data_cache(self, series->categories, has_string_cache);
1691
+
1692
+ lxw_xml_end_tag(self->file, "c:cat");
1693
+ }
1694
+
1695
+ /*
1696
+ * Write the <c:xVal> element.
1697
+ */
1698
+ STATIC void
1699
+ _chart_write_x_val(lxw_chart *self, lxw_chart_series *series)
1700
+ {
1701
+ uint8_t has_string_cache = series->categories->has_string_cache;
1702
+
1703
+ lxw_xml_start_tag(self->file, "c:xVal", NULL);
1704
+
1705
+ /* Write the data cache elements. */
1706
+ _chart_write_data_cache(self, series->categories, has_string_cache);
1707
+
1708
+ lxw_xml_end_tag(self->file, "c:xVal");
1709
+ }
1710
+
1711
+ /*
1712
+ * Write the <c:val> element.
1713
+ */
1714
+ STATIC void
1715
+ _chart_write_val(lxw_chart *self, lxw_chart_series *series)
1716
+ {
1717
+ lxw_xml_start_tag(self->file, "c:val", NULL);
1718
+
1719
+ /* Write the data cache elements. The string_cache is set to false since
1720
+ * this should always be a number series. */
1721
+ _chart_write_data_cache(self, series->values, LXW_FALSE);
1722
+
1723
+ lxw_xml_end_tag(self->file, "c:val");
1724
+ }
1725
+
1726
+ /*
1727
+ * Write the <c:yVal> element.
1728
+ */
1729
+ STATIC void
1730
+ _chart_write_y_val(lxw_chart *self, lxw_chart_series *series)
1731
+ {
1732
+ lxw_xml_start_tag(self->file, "c:yVal", NULL);
1733
+
1734
+ /* Write the data cache elements. The string_cache is set to false since
1735
+ * this should always be a number series. */
1736
+ _chart_write_data_cache(self, series->values, LXW_FALSE);
1737
+
1738
+ lxw_xml_end_tag(self->file, "c:yVal");
1739
+ }
1740
+
1741
+ /*
1742
+ * Write the <c:ser> element.
1743
+ */
1744
+ STATIC void
1745
+ _chart_write_ser(lxw_chart *self, lxw_chart_series *series)
1746
+ {
1747
+ uint16_t index = self->series_index++;
1748
+
1749
+ lxw_xml_start_tag(self->file, "c:ser", NULL);
1750
+
1751
+ /* Write the c:idx element. */
1752
+ _chart_write_idx(self, index);
1753
+
1754
+ /* Write the c:order element. */
1755
+ _chart_write_order(self, index);
1756
+
1757
+ /* Write the series name. */
1758
+ _chart_write_series_name(self, series);
1759
+
1760
+ /* Write the c:spPr element. */
1761
+ _chart_write_sp_pr(self, series->line, series->fill);
1762
+
1763
+ /* Write the c:marker element. */
1764
+ _chart_write_marker(self);
1765
+
1766
+ /* Write the c:cat element. */
1767
+ _chart_write_cat(self, series);
1768
+
1769
+ /* Write the c:val element. */
1770
+ _chart_write_val(self, series);
1771
+
1772
+ lxw_xml_end_tag(self->file, "c:ser");
1773
+ }
1774
+
1775
+ /*
1776
+ * Write the <c:ser> element but with c:xVal/c:yVal instead of c:cat/c:val
1777
+ * elements.
1778
+ */
1779
+ STATIC void
1780
+ _chart_write_xval_ser(lxw_chart *self, lxw_chart_series *series)
1781
+ {
1782
+ uint16_t index = self->series_index++;
1783
+
1784
+ lxw_xml_start_tag(self->file, "c:ser", NULL);
1785
+
1786
+ /* Write the c:idx element. */
1787
+ _chart_write_idx(self, index);
1788
+
1789
+ /* Write the c:order element. */
1790
+ _chart_write_order(self, index);
1791
+
1792
+ /* Write the series name. */
1793
+ _chart_write_series_name(self, series);
1794
+
1795
+ /* Write the c:spPr element. */
1796
+ _chart_write_sp_pr(self, series->line, series->fill);
1797
+
1798
+ if (self->type == LXW_CHART_SCATTER_STRAIGHT
1799
+ || self->type == LXW_CHART_SCATTER_SMOOTH) {
1800
+ /* Write the c:marker element. */
1801
+ _chart_write_marker(self);
1802
+ }
1803
+
1804
+ /* Write the c:xVal element. */
1805
+ _chart_write_x_val(self, series);
1806
+
1807
+ /* Write the yVal element. */
1808
+ _chart_write_y_val(self, series);
1809
+
1810
+ if (self->type == LXW_CHART_SCATTER_SMOOTH
1811
+ || self->type == LXW_CHART_SCATTER_SMOOTH_WITH_MARKERS) {
1812
+ /* Write the c:smooth element. */
1813
+ _chart_write_smooth(self);
1814
+ }
1815
+
1816
+ lxw_xml_end_tag(self->file, "c:ser");
1817
+ }
1818
+
1819
+ /*
1820
+ * Write the <c:orientation> element.
1821
+ */
1822
+ STATIC void
1823
+ _chart_write_orientation(lxw_chart *self)
1824
+ {
1825
+ struct xml_attribute_list attributes;
1826
+ struct xml_attribute *attribute;
1827
+ char val[] = "minMax";
1828
+
1829
+ LXW_INIT_ATTRIBUTES();
1830
+ LXW_PUSH_ATTRIBUTES_STR("val", val);
1831
+
1832
+ lxw_xml_empty_tag(self->file, "c:orientation", &attributes);
1833
+
1834
+ LXW_FREE_ATTRIBUTES();
1835
+ }
1836
+
1837
+ /*
1838
+ * Write the <c:scaling> element.
1839
+ */
1840
+ STATIC void
1841
+ _chart_write_scaling(lxw_chart *self)
1842
+ {
1843
+ lxw_xml_start_tag(self->file, "c:scaling", NULL);
1844
+
1845
+ /* Write the c:orientation element. */
1846
+ _chart_write_orientation(self);
1847
+
1848
+ lxw_xml_end_tag(self->file, "c:scaling");
1849
+ }
1850
+
1851
+ /*
1852
+ * Write the <c:axPos> element.
1853
+ */
1854
+ STATIC void
1855
+ _chart_write_axis_pos(lxw_chart *self, uint8_t position)
1856
+ {
1857
+ struct xml_attribute_list attributes;
1858
+ struct xml_attribute *attribute;
1859
+
1860
+ LXW_INIT_ATTRIBUTES();
1861
+
1862
+ if (position == LXW_CHART_AXIS_RIGHT)
1863
+ LXW_PUSH_ATTRIBUTES_STR("val", "r");
1864
+ else if (position == LXW_CHART_AXIS_LEFT)
1865
+ LXW_PUSH_ATTRIBUTES_STR("val", "l");
1866
+ else if (position == LXW_CHART_AXIS_TOP)
1867
+ LXW_PUSH_ATTRIBUTES_STR("val", "t");
1868
+ else if (position == LXW_CHART_AXIS_BOTTOM)
1869
+ LXW_PUSH_ATTRIBUTES_STR("val", "b");
1870
+
1871
+ lxw_xml_empty_tag(self->file, "c:axPos", &attributes);
1872
+
1873
+ LXW_FREE_ATTRIBUTES();
1874
+ }
1875
+
1876
+ /*
1877
+ * Write the <c:tickLblPos> element.
1878
+ */
1879
+ STATIC void
1880
+ _chart_write_tick_lbl_pos(lxw_chart *self)
1881
+ {
1882
+ struct xml_attribute_list attributes;
1883
+ struct xml_attribute *attribute;
1884
+ char val[] = "nextTo";
1885
+
1886
+ LXW_INIT_ATTRIBUTES();
1887
+ LXW_PUSH_ATTRIBUTES_STR("val", val);
1888
+
1889
+ lxw_xml_empty_tag(self->file, "c:tickLblPos", &attributes);
1890
+
1891
+ LXW_FREE_ATTRIBUTES();
1892
+ }
1893
+
1894
+ /*
1895
+ * Write the <c:crossAx> element.
1896
+ */
1897
+ STATIC void
1898
+ _chart_write_cross_axis(lxw_chart *self, uint32_t axis_id)
1899
+ {
1900
+ struct xml_attribute_list attributes;
1901
+ struct xml_attribute *attribute;
1902
+
1903
+ LXW_INIT_ATTRIBUTES();
1904
+ LXW_PUSH_ATTRIBUTES_INT("val", axis_id);
1905
+
1906
+ lxw_xml_empty_tag(self->file, "c:crossAx", &attributes);
1907
+
1908
+ LXW_FREE_ATTRIBUTES();
1909
+ }
1910
+
1911
+ /*
1912
+ * Write the <c:crosses> element.
1913
+ */
1914
+ STATIC void
1915
+ _chart_write_crosses(lxw_chart *self)
1916
+ {
1917
+ struct xml_attribute_list attributes;
1918
+ struct xml_attribute *attribute;
1919
+ char val[] = "autoZero";
1920
+
1921
+ LXW_INIT_ATTRIBUTES();
1922
+ LXW_PUSH_ATTRIBUTES_STR("val", val);
1923
+
1924
+ lxw_xml_empty_tag(self->file, "c:crosses", &attributes);
1925
+
1926
+ LXW_FREE_ATTRIBUTES();
1927
+ }
1928
+
1929
+ /*
1930
+ * Write the <c:auto> element.
1931
+ */
1932
+ STATIC void
1933
+ _chart_write_auto(lxw_chart *self)
1934
+ {
1935
+ struct xml_attribute_list attributes;
1936
+ struct xml_attribute *attribute;
1937
+ char val[] = "1";
1938
+
1939
+ LXW_INIT_ATTRIBUTES();
1940
+ LXW_PUSH_ATTRIBUTES_STR("val", val);
1941
+
1942
+ lxw_xml_empty_tag(self->file, "c:auto", &attributes);
1943
+
1944
+ LXW_FREE_ATTRIBUTES();
1945
+ }
1946
+
1947
+ /*
1948
+ * Write the <c:lblAlgn> element.
1949
+ */
1950
+ STATIC void
1951
+ _chart_write_lbl_algn(lxw_chart *self)
1952
+ {
1953
+ struct xml_attribute_list attributes;
1954
+ struct xml_attribute *attribute;
1955
+ char val[] = "ctr";
1956
+
1957
+ LXW_INIT_ATTRIBUTES();
1958
+ LXW_PUSH_ATTRIBUTES_STR("val", val);
1959
+
1960
+ lxw_xml_empty_tag(self->file, "c:lblAlgn", &attributes);
1961
+
1962
+ LXW_FREE_ATTRIBUTES();
1963
+ }
1964
+
1965
+ /*
1966
+ * Write the <c:lblOffset> element.
1967
+ */
1968
+ STATIC void
1969
+ _chart_write_lbl_offset(lxw_chart *self)
1970
+ {
1971
+ struct xml_attribute_list attributes;
1972
+ struct xml_attribute *attribute;
1973
+ char val[] = "100";
1974
+
1975
+ LXW_INIT_ATTRIBUTES();
1976
+ LXW_PUSH_ATTRIBUTES_STR("val", val);
1977
+
1978
+ lxw_xml_empty_tag(self->file, "c:lblOffset", &attributes);
1979
+
1980
+ LXW_FREE_ATTRIBUTES();
1981
+ }
1982
+
1983
+ /*
1984
+ * Write the <c:majorGridlines> element.
1985
+ */
1986
+ STATIC void
1987
+ _chart_write_major_gridlines(lxw_chart *self, lxw_chart_axis *axis)
1988
+ {
1989
+
1990
+ if (axis->default_major_gridlines)
1991
+ lxw_xml_empty_tag(self->file, "c:majorGridlines", NULL);
1992
+ }
1993
+
1994
+ /*
1995
+ * Write the <c:numFmt> element.
1996
+ */
1997
+ STATIC void
1998
+ _chart_write_number_format(lxw_chart *self, lxw_chart_axis *axis)
1999
+ {
2000
+ struct xml_attribute_list attributes;
2001
+ struct xml_attribute *attribute;
2002
+ char source_linked[] = "1";
2003
+
2004
+ LXW_INIT_ATTRIBUTES();
2005
+ LXW_PUSH_ATTRIBUTES_STR("formatCode", axis->default_num_format);
2006
+ LXW_PUSH_ATTRIBUTES_STR("sourceLinked", source_linked);
2007
+
2008
+ lxw_xml_empty_tag(self->file, "c:numFmt", &attributes);
2009
+
2010
+ LXW_FREE_ATTRIBUTES();
2011
+ }
2012
+
2013
+ /*
2014
+ * Write the <c:crossBetween> element.
2015
+ */
2016
+ STATIC void
2017
+ _chart_write_cross_between(lxw_chart *self)
2018
+ {
2019
+ struct xml_attribute_list attributes;
2020
+ struct xml_attribute *attribute;
2021
+
2022
+ LXW_INIT_ATTRIBUTES();
2023
+
2024
+ if (self->cross_between)
2025
+ LXW_PUSH_ATTRIBUTES_STR("val", "midCat");
2026
+ else
2027
+ LXW_PUSH_ATTRIBUTES_STR("val", "between");
2028
+
2029
+ lxw_xml_empty_tag(self->file, "c:crossBetween", &attributes);
2030
+
2031
+ LXW_FREE_ATTRIBUTES();
2032
+ }
2033
+
2034
+ /*
2035
+ * Write the <c:overlay> element.
2036
+ */
2037
+ STATIC void
2038
+ _chart_write_overlay(lxw_chart *self)
2039
+ {
2040
+ struct xml_attribute_list attributes;
2041
+ struct xml_attribute *attribute;
2042
+
2043
+ LXW_INIT_ATTRIBUTES();
2044
+ LXW_PUSH_ATTRIBUTES_STR("val", "1");
2045
+
2046
+ lxw_xml_empty_tag(self->file, "c:overlay", &attributes);
2047
+
2048
+ LXW_FREE_ATTRIBUTES();
2049
+ }
2050
+
2051
+ /*
2052
+ * Write the <c:legendPos> element.
2053
+ */
2054
+ STATIC void
2055
+ _chart_write_legend_pos(lxw_chart *self, char *position)
2056
+ {
2057
+ struct xml_attribute_list attributes;
2058
+ struct xml_attribute *attribute;
2059
+
2060
+ LXW_INIT_ATTRIBUTES();
2061
+
2062
+ LXW_PUSH_ATTRIBUTES_STR("val", position);
2063
+
2064
+ lxw_xml_empty_tag(self->file, "c:legendPos", &attributes);
2065
+
2066
+ LXW_FREE_ATTRIBUTES();
2067
+ }
2068
+
2069
+ /*
2070
+ * Write the <c:legendEntry> element.
2071
+ */
2072
+ STATIC void
2073
+ _chart_write_legend_entry(lxw_chart *self, uint16_t index)
2074
+ {
2075
+ lxw_xml_start_tag(self->file, "c:legendEntry", NULL);
2076
+
2077
+ /* Write the c:idx element. */
2078
+ _chart_write_idx(self, self->delete_series[index]);
2079
+
2080
+ /* Write the c:delete element. */
2081
+ _chart_write_delete(self);
2082
+
2083
+ lxw_xml_end_tag(self->file, "c:legendEntry");
2084
+ }
2085
+
2086
+ /*
2087
+ * Write the <c:legend> element.
2088
+ */
2089
+ STATIC void
2090
+ _chart_write_legend(lxw_chart *self)
2091
+ {
2092
+ uint8_t has_overlay = LXW_FALSE;
2093
+ uint16_t index;
2094
+
2095
+ if (self->legend.position == LXW_CHART_LEGEND_NONE)
2096
+ return;
2097
+
2098
+ lxw_xml_start_tag(self->file, "c:legend", NULL);
2099
+
2100
+ /* Write the c:legendPos element. */
2101
+ switch (self->legend.position) {
2102
+ case LXW_CHART_LEGEND_LEFT:
2103
+ _chart_write_legend_pos(self, "l");
2104
+ break;
2105
+ case LXW_CHART_LEGEND_TOP:
2106
+ _chart_write_legend_pos(self, "t");
2107
+ break;
2108
+ case LXW_CHART_LEGEND_BOTTOM:
2109
+ _chart_write_legend_pos(self, "b");
2110
+ break;
2111
+ case LXW_CHART_LEGEND_OVERLAY_RIGHT:
2112
+ _chart_write_legend_pos(self, "r");
2113
+ has_overlay = LXW_TRUE;
2114
+ break;
2115
+ case LXW_CHART_LEGEND_OVERLAY_LEFT:
2116
+ _chart_write_legend_pos(self, "l");
2117
+ has_overlay = LXW_TRUE;
2118
+ break;
2119
+ default:
2120
+ _chart_write_legend_pos(self, "r");
2121
+ }
2122
+
2123
+ /* Remove series labels from the legend. */
2124
+ for (index = 0; index < self->delete_series_count; index++) {
2125
+ /* Write the c:legendEntry element. */
2126
+ _chart_write_legend_entry(self, index);
2127
+ }
2128
+
2129
+ /* Write the c:layout element. */
2130
+ _chart_write_layout(self);
2131
+
2132
+ if (self->type == LXW_CHART_PIE || self->type == LXW_CHART_DOUGHNUT) {
2133
+ /* Write the c:overlay element. */
2134
+ if (has_overlay)
2135
+ _chart_write_overlay(self);
2136
+
2137
+ /* Write the c:txPr element for Pie/Doughnut charts. */
2138
+ _chart_write_tx_pr_pie(self, LXW_FALSE, self->legend.font);
2139
+ }
2140
+ else {
2141
+ /* Write the c:txPr element for all other charts. */
2142
+ if (self->legend.font)
2143
+ _chart_write_tx_pr(self, LXW_FALSE, self->legend.font);
2144
+
2145
+ /* Write the c:overlay element. */
2146
+ if (has_overlay)
2147
+ _chart_write_overlay(self);
2148
+ }
2149
+
2150
+ lxw_xml_end_tag(self->file, "c:legend");
2151
+ }
2152
+
2153
+ /*
2154
+ * Write the <c:plotVisOnly> element.
2155
+ */
2156
+ STATIC void
2157
+ _chart_write_plot_vis_only(lxw_chart *self)
2158
+ {
2159
+ struct xml_attribute_list attributes;
2160
+ struct xml_attribute *attribute;
2161
+
2162
+ LXW_INIT_ATTRIBUTES();
2163
+ LXW_PUSH_ATTRIBUTES_STR("val", "1");
2164
+
2165
+ lxw_xml_empty_tag(self->file, "c:plotVisOnly", &attributes);
2166
+
2167
+ LXW_FREE_ATTRIBUTES();
2168
+ }
2169
+
2170
+ /*
2171
+ * Write the <c:headerFooter> element.
2172
+ */
2173
+ STATIC void
2174
+ _chart_write_header_footer(lxw_chart *self)
2175
+ {
2176
+ lxw_xml_empty_tag(self->file, "c:headerFooter", NULL);
2177
+ }
2178
+
2179
+ /*
2180
+ * Write the <c:pageMargins> element.
2181
+ */
2182
+ STATIC void
2183
+ _chart_write_page_margins(lxw_chart *self)
2184
+ {
2185
+ struct xml_attribute_list attributes;
2186
+ struct xml_attribute *attribute;
2187
+ char b[] = "0.75";
2188
+ char l[] = "0.7";
2189
+ char r[] = "0.7";
2190
+ char t[] = "0.75";
2191
+ char header[] = "0.3";
2192
+ char footer[] = "0.3";
2193
+
2194
+ LXW_INIT_ATTRIBUTES();
2195
+ LXW_PUSH_ATTRIBUTES_STR("b", b);
2196
+ LXW_PUSH_ATTRIBUTES_STR("l", l);
2197
+ LXW_PUSH_ATTRIBUTES_STR("r", r);
2198
+ LXW_PUSH_ATTRIBUTES_STR("t", t);
2199
+ LXW_PUSH_ATTRIBUTES_STR("header", header);
2200
+ LXW_PUSH_ATTRIBUTES_STR("footer", footer);
2201
+
2202
+ lxw_xml_empty_tag(self->file, "c:pageMargins", &attributes);
2203
+
2204
+ LXW_FREE_ATTRIBUTES();
2205
+ }
2206
+
2207
+ /*
2208
+ * Write the <c:pageSetup> element.
2209
+ */
2210
+ STATIC void
2211
+ _chart_write_page_setup(lxw_chart *self)
2212
+ {
2213
+ lxw_xml_empty_tag(self->file, "c:pageSetup", NULL);
2214
+ }
2215
+
2216
+ /*
2217
+ * Write the <c:printSettings> element.
2218
+ */
2219
+ STATIC void
2220
+ _chart_write_print_settings(lxw_chart *self)
2221
+ {
2222
+ lxw_xml_start_tag(self->file, "c:printSettings", NULL);
2223
+
2224
+ /* Write the c:headerFooter element. */
2225
+ _chart_write_header_footer(self);
2226
+
2227
+ /* Write the c:pageMargins element. */
2228
+ _chart_write_page_margins(self);
2229
+
2230
+ /* Write the c:pageSetup element. */
2231
+ _chart_write_page_setup(self);
2232
+
2233
+ lxw_xml_end_tag(self->file, "c:printSettings");
2234
+ }
2235
+
2236
+ /*
2237
+ * Write the <c:overlap> element.
2238
+ */
2239
+ STATIC void
2240
+ _chart_write_overlap(lxw_chart *self, int overlap)
2241
+ {
2242
+ struct xml_attribute_list attributes;
2243
+ struct xml_attribute *attribute;
2244
+
2245
+ LXW_INIT_ATTRIBUTES();
2246
+ LXW_PUSH_ATTRIBUTES_INT("val", overlap);
2247
+
2248
+ lxw_xml_empty_tag(self->file, "c:overlap", &attributes);
2249
+
2250
+ LXW_FREE_ATTRIBUTES();
2251
+ }
2252
+
2253
+ /*
2254
+ * Write the <c:title> element.
2255
+ */
2256
+ STATIC void
2257
+ _chart_write_title(lxw_chart *self, lxw_chart_title *title)
2258
+ {
2259
+ if (title->name) {
2260
+ /* Write the c:title element. */
2261
+ _chart_write_title_rich(self, title);
2262
+ }
2263
+ else if (title->range->formula) {
2264
+ /* Write the c:title element. */
2265
+ _chart_write_title_formula(self, title);
2266
+ }
2267
+ }
2268
+
2269
+ /*
2270
+ * Write the <c:title> element.
2271
+ */
2272
+ STATIC void
2273
+ _chart_write_chart_title(lxw_chart *self)
2274
+ {
2275
+ if (self->title.off) {
2276
+ /* Write the c:autoTitleDeleted element. */
2277
+ _chart_write_auto_title_deleted(self);
2278
+ }
2279
+ else {
2280
+ /* Write the c:title element. */
2281
+ _chart_write_title(self, &self->title);
2282
+ }
2283
+ }
2284
+
2285
+ /*
2286
+ * Write the <c:catAx> element. Usually the X axis.
2287
+ */
2288
+ STATIC void
2289
+ _chart_write_cat_axis(lxw_chart *self)
2290
+ {
2291
+ uint8_t position = self->cat_axis_position;
2292
+
2293
+ lxw_xml_start_tag(self->file, "c:catAx", NULL);
2294
+
2295
+ _chart_write_axis_id(self, self->axis_id_1);
2296
+
2297
+ /* Write the c:scaling element. */
2298
+ _chart_write_scaling(self);
2299
+
2300
+ /* Write the c:axPos element. */
2301
+ _chart_write_axis_pos(self, position);
2302
+
2303
+ /* Write the c:majorGridlines element. */
2304
+ _chart_write_major_gridlines(self, self->x_axis);
2305
+
2306
+ /* Write the axis title elements. */
2307
+ self->x_axis->title.is_horizontal = self->has_horiz_cat_axis;
2308
+ _chart_write_title(self, &self->x_axis->title);
2309
+
2310
+ /* Write the c:numFmt element. */
2311
+ if (self->cat_has_num_fmt)
2312
+ _chart_write_number_format(self, self->x_axis);
2313
+
2314
+ /* Write the c:majorTickMark element. */
2315
+ _chart_write_major_tick_mark(self, self->x_axis);
2316
+
2317
+ /* Write the c:tickLblPos element. */
2318
+ _chart_write_tick_lbl_pos(self);
2319
+
2320
+ /* Write the c:spPr element for the axis line. */
2321
+ _chart_write_sp_pr(self, self->x_axis->line, self->x_axis->fill);
2322
+
2323
+ /* Write the axis font elements. */
2324
+ _chart_write_axis_font(self, self->x_axis->num_font);
2325
+
2326
+ /* Write the c:crossAx element. */
2327
+ _chart_write_cross_axis(self, self->axis_id_2);
2328
+
2329
+ /* Write the c:crosses element. */
2330
+ _chart_write_crosses(self);
2331
+
2332
+ /* Write the c:auto element. */
2333
+ _chart_write_auto(self);
2334
+
2335
+ /* Write the c:lblAlgn element. */
2336
+ _chart_write_lbl_algn(self);
2337
+
2338
+ /* Write the c:lblOffset element. */
2339
+ _chart_write_lbl_offset(self);
2340
+
2341
+ lxw_xml_end_tag(self->file, "c:catAx");
2342
+ }
2343
+
2344
+ /*
2345
+ * Write the <c:valAx> element.
2346
+ */
2347
+ STATIC void
2348
+ _chart_write_val_axis(lxw_chart *self)
2349
+ {
2350
+ uint8_t position = self->val_axis_position;
2351
+
2352
+ lxw_xml_start_tag(self->file, "c:valAx", NULL);
2353
+
2354
+ _chart_write_axis_id(self, self->axis_id_2);
2355
+
2356
+ /* Write the c:scaling element. */
2357
+ _chart_write_scaling(self);
2358
+
2359
+ /* Write the c:axPos element. */
2360
+ _chart_write_axis_pos(self, position);
2361
+
2362
+ /* Write the c:majorGridlines element. */
2363
+ _chart_write_major_gridlines(self, self->y_axis);
2364
+
2365
+ /* Write the axis title elements. */
2366
+ self->y_axis->title.is_horizontal = self->has_horiz_val_axis;
2367
+ _chart_write_title(self, &self->y_axis->title);
2368
+
2369
+ /* Write the c:numFmt element. */
2370
+ _chart_write_number_format(self, self->y_axis);
2371
+
2372
+ /* Write the c:majorTickMark element. */
2373
+ _chart_write_major_tick_mark(self, self->y_axis);
2374
+
2375
+ /* Write the c:tickLblPos element. */
2376
+ _chart_write_tick_lbl_pos(self);
2377
+
2378
+ /* Write the c:spPr element for the axis line. */
2379
+ _chart_write_sp_pr(self, self->y_axis->line, self->y_axis->fill);
2380
+
2381
+ /* Write the axis font elements. */
2382
+ _chart_write_axis_font(self, self->y_axis->num_font);
2383
+
2384
+ /* Write the c:crossAx element. */
2385
+ _chart_write_cross_axis(self, self->axis_id_1);
2386
+
2387
+ /* Write the c:crosses element. */
2388
+ _chart_write_crosses(self);
2389
+
2390
+ /* Write the c:crossBetween element. */
2391
+ _chart_write_cross_between(self);
2392
+
2393
+ lxw_xml_end_tag(self->file, "c:valAx");
2394
+ }
2395
+
2396
+ /*
2397
+ * Write the <c:valAx> element. This is for the second valAx in scatter plots.
2398
+ */
2399
+ STATIC void
2400
+ _chart_write_cat_val_axis(lxw_chart *self)
2401
+ {
2402
+ uint8_t position = self->cat_axis_position;
2403
+
2404
+ lxw_xml_start_tag(self->file, "c:valAx", NULL);
2405
+
2406
+ _chart_write_axis_id(self, self->axis_id_1);
2407
+
2408
+ /* Write the c:scaling element. */
2409
+ _chart_write_scaling(self);
2410
+
2411
+ /* Write the c:axPos element. */
2412
+ _chart_write_axis_pos(self, position);
2413
+
2414
+ /* Write the axis title elements. */
2415
+ self->x_axis->title.is_horizontal = self->has_horiz_val_axis;
2416
+ _chart_write_title(self, &self->x_axis->title);
2417
+
2418
+ /* Write the c:numFmt element. */
2419
+ _chart_write_number_format(self, self->x_axis);
2420
+
2421
+ /* Write the c:majorTickMark element. */
2422
+ _chart_write_major_tick_mark(self, self->x_axis);
2423
+
2424
+ /* Write the c:tickLblPos element. */
2425
+ _chart_write_tick_lbl_pos(self);
2426
+
2427
+ /* Write the c:spPr element for the axis line. */
2428
+ _chart_write_sp_pr(self, self->x_axis->line, self->x_axis->fill);
2429
+
2430
+ /* Write the axis font elements. */
2431
+ _chart_write_axis_font(self, self->x_axis->num_font);
2432
+
2433
+ /* Write the c:crossAx element. */
2434
+ _chart_write_cross_axis(self, self->axis_id_2);
2435
+
2436
+ /* Write the c:crosses element. */
2437
+ _chart_write_crosses(self);
2438
+
2439
+ /* Write the c:crossBetween element. */
2440
+ _chart_write_cross_between(self);
2441
+
2442
+ lxw_xml_end_tag(self->file, "c:valAx");
2443
+ }
2444
+
2445
+ /*
2446
+ * Write the <c:barDir> element.
2447
+ */
2448
+ STATIC void
2449
+ _chart_write_bar_dir(lxw_chart *self, char *type)
2450
+ {
2451
+ struct xml_attribute_list attributes;
2452
+ struct xml_attribute *attribute;
2453
+
2454
+ LXW_INIT_ATTRIBUTES();
2455
+ LXW_PUSH_ATTRIBUTES_STR("val", type);
2456
+
2457
+ lxw_xml_empty_tag(self->file, "c:barDir", &attributes);
2458
+
2459
+ LXW_FREE_ATTRIBUTES();
2460
+ }
2461
+
2462
+ /*
2463
+ * Write a area chart.
2464
+ */
2465
+ STATIC void
2466
+ _chart_write_area_chart(lxw_chart *self)
2467
+ {
2468
+ lxw_chart_series *series;
2469
+
2470
+ lxw_xml_start_tag(self->file, "c:areaChart", NULL);
2471
+
2472
+ /* Write the c:grouping element. */
2473
+ _chart_write_grouping(self, self->grouping);
2474
+
2475
+ STAILQ_FOREACH(series, self->series_list, list_pointers) {
2476
+ /* Write the c:ser element. */
2477
+ _chart_write_ser(self, series);
2478
+ }
2479
+
2480
+ if (self->has_overlap) {
2481
+ /* Write the c:overlap element. */
2482
+ _chart_write_overlap(self, self->series_overlap_1);
2483
+ }
2484
+
2485
+ /* Write the c:axId elements. */
2486
+ _chart_write_axis_ids(self);
2487
+
2488
+ lxw_xml_end_tag(self->file, "c:areaChart");
2489
+ }
2490
+
2491
+ /*
2492
+ * Write a bar chart.
2493
+ */
2494
+ STATIC void
2495
+ _chart_write_bar_chart(lxw_chart *self)
2496
+ {
2497
+ lxw_chart_series *series;
2498
+
2499
+ lxw_xml_start_tag(self->file, "c:barChart", NULL);
2500
+
2501
+ /* Write the c:barDir element. */
2502
+ _chart_write_bar_dir(self, "bar");
2503
+
2504
+ /* Write the c:grouping element. */
2505
+ _chart_write_grouping(self, self->grouping);
2506
+
2507
+ STAILQ_FOREACH(series, self->series_list, list_pointers) {
2508
+ /* Write the c:ser element. */
2509
+ _chart_write_ser(self, series);
2510
+ }
2511
+
2512
+ if (self->has_overlap) {
2513
+ /* Write the c:overlap element. */
2514
+ _chart_write_overlap(self, self->series_overlap_1);
2515
+ }
2516
+
2517
+ /* Write the c:axId elements. */
2518
+ _chart_write_axis_ids(self);
2519
+
2520
+ lxw_xml_end_tag(self->file, "c:barChart");
2521
+ }
2522
+
2523
+ /*
2524
+ * Write a column chart.
2525
+ */
2526
+ STATIC void
2527
+ _chart_write_column_chart(lxw_chart *self)
2528
+ {
2529
+ lxw_chart_series *series;
2530
+
2531
+ lxw_xml_start_tag(self->file, "c:barChart", NULL);
2532
+
2533
+ /* Write the c:barDir element. */
2534
+ _chart_write_bar_dir(self, "col");
2535
+
2536
+ /* Write the c:grouping element. */
2537
+ _chart_write_grouping(self, self->grouping);
2538
+
2539
+ STAILQ_FOREACH(series, self->series_list, list_pointers) {
2540
+ /* Write the c:ser element. */
2541
+ _chart_write_ser(self, series);
2542
+ }
2543
+
2544
+ if (self->has_overlap) {
2545
+ /* Write the c:overlap element. */
2546
+ _chart_write_overlap(self, self->series_overlap_1);
2547
+ }
2548
+
2549
+ /* Write the c:axId elements. */
2550
+ _chart_write_axis_ids(self);
2551
+
2552
+ lxw_xml_end_tag(self->file, "c:barChart");
2553
+ }
2554
+
2555
+ /*
2556
+ * Write a doughnut chart.
2557
+ */
2558
+ STATIC void
2559
+ _chart_write_doughnut_chart(lxw_chart *self)
2560
+ {
2561
+ lxw_chart_series *series;
2562
+
2563
+ lxw_xml_start_tag(self->file, "c:doughnutChart", NULL);
2564
+
2565
+ /* Write the c:varyColors element. */
2566
+ _chart_write_vary_colors(self);
2567
+
2568
+ STAILQ_FOREACH(series, self->series_list, list_pointers) {
2569
+ /* Write the c:ser element. */
2570
+ _chart_write_ser(self, series);
2571
+ }
2572
+
2573
+ /* Write the c:firstSliceAng element. */
2574
+ _chart_write_first_slice_ang(self);
2575
+
2576
+ /* Write the c:holeSize element. */
2577
+ _chart_write_hole_size(self);
2578
+
2579
+ lxw_xml_end_tag(self->file, "c:doughnutChart");
2580
+ }
2581
+
2582
+ /*
2583
+ * Write a line chart.
2584
+ */
2585
+ STATIC void
2586
+ _chart_write_line_chart(lxw_chart *self)
2587
+ {
2588
+ lxw_chart_series *series;
2589
+
2590
+ lxw_xml_start_tag(self->file, "c:lineChart", NULL);
2591
+
2592
+ /* Write the c:grouping element. */
2593
+ _chart_write_grouping(self, self->grouping);
2594
+
2595
+ STAILQ_FOREACH(series, self->series_list, list_pointers) {
2596
+ /* Write the c:ser element. */
2597
+ _chart_write_ser(self, series);
2598
+ }
2599
+
2600
+ /* Write the c:marker element. */
2601
+ _chart_write_marker_value(self);
2602
+
2603
+ /* Write the c:axId elements. */
2604
+ _chart_write_axis_ids(self);
2605
+
2606
+ lxw_xml_end_tag(self->file, "c:lineChart");
2607
+ }
2608
+
2609
+ /*
2610
+ * Write a pie chart.
2611
+ */
2612
+ STATIC void
2613
+ _chart_write_pie_chart(lxw_chart *self)
2614
+ {
2615
+ lxw_chart_series *series;
2616
+
2617
+ lxw_xml_start_tag(self->file, "c:pieChart", NULL);
2618
+
2619
+ /* Write the c:varyColors element. */
2620
+ _chart_write_vary_colors(self);
2621
+
2622
+ STAILQ_FOREACH(series, self->series_list, list_pointers) {
2623
+ /* Write the c:ser element. */
2624
+ _chart_write_ser(self, series);
2625
+ }
2626
+
2627
+ /* Write the c:firstSliceAng element. */
2628
+ _chart_write_first_slice_ang(self);
2629
+
2630
+ lxw_xml_end_tag(self->file, "c:pieChart");
2631
+ }
2632
+
2633
+ /*
2634
+ * Write a scatter chart.
2635
+ */
2636
+ STATIC void
2637
+ _chart_write_scatter_chart(lxw_chart *self)
2638
+ {
2639
+ lxw_chart_series *series;
2640
+
2641
+ lxw_xml_start_tag(self->file, "c:scatterChart", NULL);
2642
+
2643
+ /* Write the c:scatterStyle element. */
2644
+ _chart_write_scatter_style(self);
2645
+
2646
+ STAILQ_FOREACH(series, self->series_list, list_pointers) {
2647
+
2648
+ /* Add default scatter chart formatting to the series data unless
2649
+ * it has already been specified by the user.*/
2650
+ if (self->type == LXW_CHART_SCATTER) {
2651
+ if (!series->line) {
2652
+ lxw_chart_line line = {
2653
+ 0x000000,
2654
+ LXW_TRUE,
2655
+ 2.25,
2656
+ LXW_CHART_LINE_DASH_SOLID,
2657
+ 0,
2658
+ LXW_FALSE
2659
+ };
2660
+ series->line = _chart_convert_line_args(&line);
2661
+ }
2662
+ }
2663
+
2664
+ /* Write the c:ser element. */
2665
+ _chart_write_xval_ser(self, series);
2666
+ }
2667
+
2668
+ /* Write the c:axId elements. */
2669
+ _chart_write_axis_ids(self);
2670
+
2671
+ lxw_xml_end_tag(self->file, "c:scatterChart");
2672
+ }
2673
+
2674
+ /*
2675
+ * Write a radar chart.
2676
+ */
2677
+ STATIC void
2678
+ _chart_write_radar_chart(lxw_chart *self)
2679
+ {
2680
+ lxw_chart_series *series;
2681
+
2682
+ lxw_xml_start_tag(self->file, "c:radarChart", NULL);
2683
+
2684
+ /* Write the c:radarStyle element. */
2685
+ _chart_write_radar_style(self);
2686
+
2687
+ STAILQ_FOREACH(series, self->series_list, list_pointers) {
2688
+ /* Write the c:ser element. */
2689
+ _chart_write_ser(self, series);
2690
+ }
2691
+
2692
+ if (self->has_overlap) {
2693
+ /* Write the c:overlap element. */
2694
+ _chart_write_overlap(self, self->series_overlap_1);
2695
+ }
2696
+
2697
+ /* Write the c:axId elements. */
2698
+ _chart_write_axis_ids(self);
2699
+
2700
+ lxw_xml_end_tag(self->file, "c:radarChart");
2701
+ }
2702
+
2703
+ /*
2704
+ * Write the <c:plotArea> element.
2705
+ */
2706
+ STATIC void
2707
+ _chart_write_scatter_plot_area(lxw_chart *self)
2708
+ {
2709
+ lxw_xml_start_tag(self->file, "c:plotArea", NULL);
2710
+
2711
+ /* Write the c:layout element. */
2712
+ _chart_write_layout(self);
2713
+
2714
+ /* Write subclass chart type elements for primary and secondary axes. */
2715
+ self->write_chart_type(self);
2716
+
2717
+ /* Write the c:catAx element. */
2718
+ _chart_write_cat_val_axis(self);
2719
+
2720
+ self->has_horiz_val_axis = LXW_TRUE;
2721
+
2722
+ /* Write the c:valAx element. */
2723
+ _chart_write_val_axis(self);
2724
+
2725
+ lxw_xml_end_tag(self->file, "c:plotArea");
2726
+ }
2727
+
2728
+ /*
2729
+ * Write the <c:plotArea> element. Special handling for pie/doughnut.
2730
+ */
2731
+ STATIC void
2732
+ _chart_write_pie_plot_area(lxw_chart *self)
2733
+ {
2734
+ lxw_xml_start_tag(self->file, "c:plotArea", NULL);
2735
+
2736
+ /* Write the c:layout element. */
2737
+ _chart_write_layout(self);
2738
+
2739
+ /* Write subclass chart type elements for primary and secondary axes. */
2740
+ self->write_chart_type(self);
2741
+
2742
+ lxw_xml_end_tag(self->file, "c:plotArea");
2743
+ }
2744
+
2745
+ /*
2746
+ * Write the <c:plotArea> element.
2747
+ */
2748
+ STATIC void
2749
+ _chart_write_plot_area(lxw_chart *self)
2750
+ {
2751
+ lxw_xml_start_tag(self->file, "c:plotArea", NULL);
2752
+
2753
+ /* Write the c:layout element. */
2754
+ _chart_write_layout(self);
2755
+
2756
+ /* Write subclass chart type elements for primary and secondary axes. */
2757
+ self->write_chart_type(self);
2758
+
2759
+ /* Write the c:catAx element. */
2760
+ _chart_write_cat_axis(self);
2761
+
2762
+ /* Write the c:valAx element. */
2763
+ _chart_write_val_axis(self);
2764
+
2765
+ lxw_xml_end_tag(self->file, "c:plotArea");
2766
+ }
2767
+
2768
+ /*
2769
+ * Write the <c:chart> element.
2770
+ */
2771
+ STATIC void
2772
+ _chart_write_chart(lxw_chart *self)
2773
+ {
2774
+ lxw_xml_start_tag(self->file, "c:chart", NULL);
2775
+
2776
+ /* Write the c:title element. */
2777
+ _chart_write_chart_title(self);
2778
+
2779
+ /* Write the c:plotArea element. */
2780
+ self->write_plot_area(self);
2781
+
2782
+ /* Write the c:legend element. */
2783
+ _chart_write_legend(self);
2784
+
2785
+ /* Write the c:plotVisOnly element. */
2786
+ _chart_write_plot_vis_only(self);
2787
+
2788
+ lxw_xml_end_tag(self->file, "c:chart");
2789
+ }
2790
+
2791
+ /*
2792
+ * Initialize a area chart.
2793
+ */
2794
+ STATIC void
2795
+ _chart_initialize_area_chart(lxw_chart *self, uint8_t type)
2796
+ {
2797
+ self->grouping = LXW_GROUPING_STANDARD;
2798
+ self->cross_between = LXW_CHART_AXIS_POSITION_ON_TICK;
2799
+
2800
+ if (type == LXW_CHART_AREA_STACKED) {
2801
+ self->grouping = LXW_GROUPING_STACKED;
2802
+ self->subtype = LXW_CHART_SUBTYPE_STACKED;
2803
+ }
2804
+
2805
+ if (type == LXW_CHART_AREA_STACKED_PERCENT) {
2806
+ self->grouping = LXW_GROUPING_PERCENTSTACKED;
2807
+ lxw_strcpy((self->y_axis)->default_num_format, "0%");
2808
+ self->subtype = LXW_CHART_SUBTYPE_STACKED;
2809
+ }
2810
+
2811
+ /* Initialize the function pointers for this chart type. */
2812
+ self->write_chart_type = _chart_write_area_chart;
2813
+ self->write_plot_area = _chart_write_plot_area;
2814
+ }
2815
+
2816
+ /*
2817
+ * Initialize a bar chart.
2818
+ */
2819
+ STATIC void
2820
+ _chart_initialize_bar_chart(lxw_chart *self, uint8_t type)
2821
+ {
2822
+ lxw_chart_axis *tmp;
2823
+
2824
+ /* Reverse the X and Y axes for Bar charts. */
2825
+ tmp = self->x_axis;
2826
+ self->x_axis = self->y_axis;
2827
+ self->y_axis = tmp;
2828
+
2829
+ /*Also reverse some of the defaults. */
2830
+ self->x_axis->default_major_gridlines = LXW_FALSE;
2831
+ self->y_axis->default_major_gridlines = LXW_TRUE;
2832
+ self->has_horiz_cat_axis = LXW_TRUE;
2833
+ self->has_horiz_val_axis = LXW_FALSE;
2834
+
2835
+ if (type == LXW_CHART_BAR_STACKED) {
2836
+ self->grouping = LXW_GROUPING_STACKED;
2837
+ self->has_overlap = LXW_TRUE;
2838
+ self->subtype = LXW_CHART_SUBTYPE_STACKED;
2839
+ }
2840
+
2841
+ if (type == LXW_CHART_BAR_STACKED_PERCENT) {
2842
+ self->grouping = LXW_GROUPING_PERCENTSTACKED;
2843
+ lxw_strcpy((self->y_axis)->default_num_format, "0%");
2844
+ self->has_overlap = LXW_TRUE;
2845
+ self->subtype = LXW_CHART_SUBTYPE_STACKED;
2846
+ }
2847
+
2848
+ /* Override the default axis positions for a bar chart. */
2849
+ self->cat_axis_position = LXW_CHART_AXIS_LEFT;
2850
+ self->val_axis_position = LXW_CHART_AXIS_BOTTOM;
2851
+
2852
+ /* Initialize the function pointers for this chart type. */
2853
+ self->write_chart_type = _chart_write_bar_chart;
2854
+ self->write_plot_area = _chart_write_plot_area;
2855
+ }
2856
+
2857
+ /*
2858
+ * Initialize a column chart.
2859
+ */
2860
+ STATIC void
2861
+ _chart_initialize_column_chart(lxw_chart *self, uint8_t type)
2862
+ {
2863
+ self->has_horiz_val_axis = LXW_FALSE;
2864
+
2865
+ if (type == LXW_CHART_COLUMN_STACKED) {
2866
+ self->grouping = LXW_GROUPING_STACKED;
2867
+ self->has_overlap = LXW_TRUE;
2868
+ self->subtype = LXW_CHART_SUBTYPE_STACKED;
2869
+ }
2870
+
2871
+ if (type == LXW_CHART_COLUMN_STACKED_PERCENT) {
2872
+ self->grouping = LXW_GROUPING_PERCENTSTACKED;
2873
+ lxw_strcpy((self->y_axis)->default_num_format, "0%");
2874
+ self->has_overlap = LXW_TRUE;
2875
+ self->subtype = LXW_CHART_SUBTYPE_STACKED;
2876
+ }
2877
+
2878
+ /* Initialize the function pointers for this chart type. */
2879
+ self->write_chart_type = _chart_write_column_chart;
2880
+ self->write_plot_area = _chart_write_plot_area;
2881
+ }
2882
+
2883
+ /*
2884
+ * Initialize a doughnut chart.
2885
+ */
2886
+ STATIC void
2887
+ _chart_initialize_doughnut_chart(lxw_chart *self)
2888
+ {
2889
+ self->has_markers = LXW_FALSE;
2890
+
2891
+ /* Initialize the function pointers for this chart type. */
2892
+ self->write_chart_type = _chart_write_doughnut_chart;
2893
+ self->write_plot_area = _chart_write_pie_plot_area;
2894
+ }
2895
+
2896
+ /*
2897
+ * Initialize a line chart.
2898
+ */
2899
+ STATIC void
2900
+ _chart_initialize_line_chart(lxw_chart *self)
2901
+ {
2902
+ self->has_markers = LXW_TRUE;
2903
+ self->grouping = LXW_GROUPING_STANDARD;
2904
+
2905
+ /* Initialize the function pointers for this chart type. */
2906
+ self->write_chart_type = _chart_write_line_chart;
2907
+ self->write_plot_area = _chart_write_plot_area;
2908
+ }
2909
+
2910
+ /*
2911
+ * Initialize a pie chart.
2912
+ */
2913
+ STATIC void
2914
+ _chart_initialize_pie_chart(lxw_chart *self)
2915
+ {
2916
+ self->has_markers = LXW_FALSE;
2917
+
2918
+ /* Initialize the function pointers for this chart type. */
2919
+ self->write_chart_type = _chart_write_pie_chart;
2920
+ self->write_plot_area = _chart_write_pie_plot_area;
2921
+ }
2922
+
2923
+ /*
2924
+ * Initialize a scatter chart.
2925
+ */
2926
+ STATIC void
2927
+ _chart_initialize_scatter_chart(lxw_chart *self)
2928
+ {
2929
+ self->has_horiz_val_axis = LXW_FALSE;
2930
+ self->cross_between = LXW_CHART_AXIS_POSITION_ON_TICK;
2931
+ self->is_scatter = LXW_TRUE;
2932
+ self->has_markers = LXW_TRUE;
2933
+
2934
+ /* Initialize the function pointers for this chart type. */
2935
+ self->write_chart_type = _chart_write_scatter_chart;
2936
+ self->write_plot_area = _chart_write_scatter_plot_area;
2937
+ }
2938
+
2939
+ /*
2940
+ * Initialize a radar chart.
2941
+ */
2942
+ STATIC void
2943
+ _chart_initialize_radar_chart(lxw_chart *self, uint8_t type)
2944
+ {
2945
+ if (type == LXW_CHART_RADAR)
2946
+ self->has_markers = LXW_TRUE;
2947
+
2948
+ self->x_axis->default_major_gridlines = LXW_TRUE;
2949
+ self->y_axis->major_tick_mark = LXW_TRUE;
2950
+
2951
+ /* Initialize the function pointers for this chart type. */
2952
+ self->write_chart_type = _chart_write_radar_chart;
2953
+ self->write_plot_area = _chart_write_plot_area;
2954
+ }
2955
+
2956
+ /*
2957
+ * Initialize the chart specific properties.
2958
+ */
2959
+ STATIC void
2960
+ _chart_initialize(lxw_chart *self, uint8_t type)
2961
+ {
2962
+ switch (type) {
2963
+
2964
+ case LXW_CHART_AREA:
2965
+ case LXW_CHART_AREA_STACKED:
2966
+ case LXW_CHART_AREA_STACKED_PERCENT:
2967
+ _chart_initialize_area_chart(self, type);
2968
+ break;
2969
+
2970
+ case LXW_CHART_BAR:
2971
+ case LXW_CHART_BAR_STACKED:
2972
+ case LXW_CHART_BAR_STACKED_PERCENT:
2973
+ _chart_initialize_bar_chart(self, type);
2974
+ break;
2975
+
2976
+ case LXW_CHART_COLUMN:
2977
+ case LXW_CHART_COLUMN_STACKED:
2978
+ case LXW_CHART_COLUMN_STACKED_PERCENT:
2979
+ _chart_initialize_column_chart(self, type);
2980
+ break;
2981
+
2982
+ case LXW_CHART_DOUGHNUT:
2983
+ _chart_initialize_doughnut_chart(self);
2984
+ break;
2985
+
2986
+ case LXW_CHART_LINE:
2987
+ _chart_initialize_line_chart(self);
2988
+ break;
2989
+
2990
+ case LXW_CHART_PIE:
2991
+ _chart_initialize_pie_chart(self);
2992
+ break;
2993
+
2994
+ case LXW_CHART_SCATTER:
2995
+ case LXW_CHART_SCATTER_STRAIGHT:
2996
+ case LXW_CHART_SCATTER_STRAIGHT_WITH_MARKERS:
2997
+ case LXW_CHART_SCATTER_SMOOTH:
2998
+ case LXW_CHART_SCATTER_SMOOTH_WITH_MARKERS:
2999
+ _chart_initialize_scatter_chart(self);
3000
+ break;
3001
+
3002
+ case LXW_CHART_RADAR:
3003
+ case LXW_CHART_RADAR_WITH_MARKERS:
3004
+ case LXW_CHART_RADAR_FILLED:
3005
+ _chart_initialize_radar_chart(self, type);
3006
+ break;
3007
+
3008
+ default:
3009
+ LXW_WARN_FORMAT1("workbook_add_chart(): "
3010
+ "unhandled chart type '%d'", type);
3011
+ }
3012
+ }
3013
+
3014
+ /*
3015
+ * Assemble and write the XML file.
3016
+ */
3017
+ void
3018
+ lxw_chart_assemble_xml_file(lxw_chart *self)
3019
+ {
3020
+ /* Initialize the chart specific properties. */
3021
+ _chart_initialize(self, self->type);
3022
+
3023
+ /* Write the XML declaration. */
3024
+ _chart_xml_declaration(self);
3025
+
3026
+ /* Write the c:chartSpace element. */
3027
+ _chart_write_chart_space(self);
3028
+
3029
+ /* Write the c:lang element. */
3030
+ _chart_write_lang(self);
3031
+
3032
+ /* Write the c:style element. */
3033
+ _chart_write_style(self);
3034
+
3035
+ /* Write the c:chart element. */
3036
+ _chart_write_chart(self);
3037
+
3038
+ /* Write the c:printSettings element. */
3039
+ _chart_write_print_settings(self);
3040
+
3041
+ lxw_xml_end_tag(self->file, "c:chartSpace");
3042
+ }
3043
+
3044
+ /*****************************************************************************
3045
+ *
3046
+ * Public functions.
3047
+ *
3048
+ ****************************************************************************/
3049
+
3050
+ /*
3051
+ * Add data to a data cache in a range object, for testing only.
3052
+ */
3053
+ int
3054
+ lxw_chart_add_data_cache(lxw_series_range *range, uint8_t *data,
3055
+ uint16_t rows, uint8_t cols, uint8_t col)
3056
+ {
3057
+ struct lxw_series_data_point *data_point;
3058
+ uint16_t i;
3059
+
3060
+ range->ignore_cache = LXW_TRUE;
3061
+ range->num_data_points = rows;
3062
+
3063
+ /* Initialize the series range data cache. */
3064
+ for (i = 0; i < rows; i++) {
3065
+ data_point = calloc(1, sizeof(struct lxw_series_data_point));
3066
+ STAILQ_INSERT_TAIL(range->data_cache, data_point, list_pointers);
3067
+ data_point->number = data[i * cols + col];
3068
+ }
3069
+
3070
+ return 0;
3071
+ }
3072
+
3073
+ /*
3074
+ * Insert an image into the worksheet.
3075
+ */
3076
+ lxw_chart_series *
3077
+ chart_add_series(lxw_chart *self, const char *categories, const char *values)
3078
+ {
3079
+ lxw_chart_series *series;
3080
+
3081
+ /* Create a new object to hold the series. */
3082
+ series = calloc(1, sizeof(lxw_chart_series));
3083
+ GOTO_LABEL_ON_MEM_ERROR(series, mem_error);
3084
+
3085
+ series->categories = calloc(1, sizeof(lxw_series_range));
3086
+ GOTO_LABEL_ON_MEM_ERROR(series->categories, mem_error);
3087
+
3088
+ series->values = calloc(1, sizeof(lxw_series_range));
3089
+ GOTO_LABEL_ON_MEM_ERROR(series->values, mem_error);
3090
+
3091
+ series->title.range = calloc(1, sizeof(lxw_series_range));
3092
+ GOTO_LABEL_ON_MEM_ERROR(series->title.range, mem_error);
3093
+
3094
+ if (categories) {
3095
+ if (categories[0] == '=')
3096
+ series->categories->formula = lxw_strdup(categories + 1);
3097
+ else
3098
+ series->categories->formula = lxw_strdup(categories);
3099
+ }
3100
+
3101
+ if (values) {
3102
+ if (values[0] == '=')
3103
+ series->values->formula = lxw_strdup(values + 1);
3104
+ else
3105
+ series->values->formula = lxw_strdup(values);
3106
+ }
3107
+
3108
+ if (_chart_init_data_cache(series->categories) != LXW_NO_ERROR)
3109
+ goto mem_error;
3110
+
3111
+ if (_chart_init_data_cache(series->values) != LXW_NO_ERROR)
3112
+ goto mem_error;
3113
+
3114
+ if (_chart_init_data_cache(series->title.range) != LXW_NO_ERROR)
3115
+ goto mem_error;
3116
+
3117
+ STAILQ_INSERT_TAIL(self->series_list, series, list_pointers);
3118
+
3119
+ return series;
3120
+
3121
+ mem_error:
3122
+ _chart_series_free(series);
3123
+ return NULL;
3124
+ }
3125
+
3126
+ /*
3127
+ * Set on of the 48 built-in Excel chart styles.
3128
+ */
3129
+ void
3130
+ chart_set_style(lxw_chart *self, uint8_t style_id)
3131
+ {
3132
+ /* The default style is 2. The range is 1 - 48 */
3133
+ if (style_id < 1 || style_id > 48)
3134
+ style_id = 2;
3135
+
3136
+ self->style_id = style_id;
3137
+ }
3138
+
3139
+ /*
3140
+ * Set a user defined name for a series.
3141
+ */
3142
+ void
3143
+ chart_series_set_name(lxw_chart_series *series, const char *name)
3144
+ {
3145
+ if (!name)
3146
+ return;
3147
+
3148
+ if (name[0] == '=')
3149
+ series->title.range->formula = lxw_strdup(name + 1);
3150
+ else
3151
+ series->title.name = lxw_strdup(name);
3152
+ }
3153
+
3154
+ /*
3155
+ * Set an axis caption, with a range instead or a formula..
3156
+ */
3157
+ void
3158
+ chart_series_set_name_range(lxw_chart_series *series, const char *sheetname,
3159
+ lxw_row_t row, lxw_col_t col)
3160
+ {
3161
+ if (!sheetname) {
3162
+ LXW_WARN("chart_series_set_name_range(): "
3163
+ "sheetname must be specified");
3164
+ return;
3165
+ }
3166
+
3167
+ /* Start and end row, col are the same for single cell range. */
3168
+ _chart_set_range(series->title.range, sheetname, row, col, row, col);
3169
+ }
3170
+
3171
+ /*
3172
+ * Set the categories range for a series.
3173
+ */
3174
+ void
3175
+ chart_series_set_categories(lxw_chart_series *series, const char *sheetname,
3176
+ lxw_row_t first_row, lxw_col_t first_col,
3177
+ lxw_row_t last_row, lxw_col_t last_col)
3178
+ {
3179
+ if (!sheetname) {
3180
+ LXW_WARN("chart_series_set_categories(): "
3181
+ "sheetname must be specified");
3182
+ return;
3183
+ }
3184
+
3185
+ _chart_set_range(series->categories, sheetname,
3186
+ first_row, first_col, last_row, last_col);
3187
+ }
3188
+
3189
+ /*
3190
+ * Set the values range for a series.
3191
+ */
3192
+ void
3193
+ chart_series_set_values(lxw_chart_series *series, const char *sheetname,
3194
+ lxw_row_t first_row, lxw_col_t first_col,
3195
+ lxw_row_t last_row, lxw_col_t last_col)
3196
+ {
3197
+ if (!sheetname) {
3198
+ LXW_WARN("chart_series_set_values(): sheetname must be specified");
3199
+ return;
3200
+ }
3201
+
3202
+ _chart_set_range(series->values, sheetname,
3203
+ first_row, first_col, last_row, last_col);
3204
+ }
3205
+
3206
+ /*
3207
+ * Set a line type for a series.
3208
+ */
3209
+ void
3210
+ chart_series_set_line(lxw_chart_series *series, lxw_chart_line *line)
3211
+ {
3212
+ if (!line)
3213
+ return;
3214
+
3215
+ series->line = _chart_convert_line_args(line);
3216
+ }
3217
+
3218
+ /*
3219
+ * Set a fill type for a series.
3220
+ */
3221
+ void
3222
+ chart_series_set_fill(lxw_chart_series *series, lxw_chart_fill *fill)
3223
+ {
3224
+ if (!fill)
3225
+ return;
3226
+
3227
+ series->fill = _chart_convert_fill_args(fill);
3228
+ }
3229
+
3230
+ /*
3231
+ * Set an axis caption.
3232
+ */
3233
+ void
3234
+ chart_axis_set_name(lxw_chart_axis *axis, const char *name)
3235
+ {
3236
+ if (!name)
3237
+ return;
3238
+
3239
+ if (name[0] == '=')
3240
+ axis->title.range->formula = lxw_strdup(name + 1);
3241
+ else
3242
+ axis->title.name = lxw_strdup(name);
3243
+ }
3244
+
3245
+ /*
3246
+ * Set an axis caption, with a range instead or a formula..
3247
+ */
3248
+ void
3249
+ chart_axis_set_name_range(lxw_chart_axis *axis, const char *sheetname,
3250
+ lxw_row_t row, lxw_col_t col)
3251
+ {
3252
+ if (!sheetname) {
3253
+ LXW_WARN("chart_axis_set_name_range(): sheetname must be specified");
3254
+ return;
3255
+ }
3256
+
3257
+ /* Start and end row, col are the same for single cell range. */
3258
+ _chart_set_range(axis->title.range, sheetname, row, col, row, col);
3259
+ }
3260
+
3261
+ /*
3262
+ * Set an axis title/name font.
3263
+ */
3264
+ void
3265
+ chart_axis_set_name_font(lxw_chart_axis *axis, lxw_chart_font *font)
3266
+ {
3267
+ axis->title.font = _chart_convert_font_args(font);
3268
+ }
3269
+
3270
+ /*
3271
+ * Set an axis number font.
3272
+ */
3273
+ void
3274
+ chart_axis_set_num_font(lxw_chart_axis *axis, lxw_chart_font *font)
3275
+ {
3276
+ axis->num_font = _chart_convert_font_args(font);
3277
+ }
3278
+
3279
+ /*
3280
+ * Set a line type for an axis.
3281
+ */
3282
+ void
3283
+ chart_axis_set_line(lxw_chart_axis *axis, lxw_chart_line *line)
3284
+ {
3285
+ if (!line)
3286
+ return;
3287
+
3288
+ axis->line = _chart_convert_line_args(line);
3289
+ }
3290
+
3291
+ /*
3292
+ * Set a fill type for an axis.
3293
+ */
3294
+ void
3295
+ chart_axis_set_fill(lxw_chart_axis *axis, lxw_chart_fill *fill)
3296
+ {
3297
+ if (!fill)
3298
+ return;
3299
+
3300
+ axis->fill = _chart_convert_fill_args(fill);
3301
+ }
3302
+
3303
+ /*
3304
+ * Set the chart title.
3305
+ */
3306
+ void
3307
+ chart_title_set_name(lxw_chart *self, const char *name)
3308
+ {
3309
+ if (!name)
3310
+ return;
3311
+
3312
+ if (name[0] == '=')
3313
+ self->title.range->formula = lxw_strdup(name + 1);
3314
+ else
3315
+ self->title.name = lxw_strdup(name);
3316
+ }
3317
+
3318
+ /*
3319
+ * Set the chart title, with a range instead or a formula.
3320
+ */
3321
+ void
3322
+ chart_title_set_name_range(lxw_chart *self, const char *sheetname,
3323
+ lxw_row_t row, lxw_col_t col)
3324
+ {
3325
+ if (!sheetname) {
3326
+ LXW_WARN("chart_title_set_name_range(): sheetname must be specified");
3327
+ return;
3328
+ }
3329
+
3330
+ /* Start and end row, col are the same for single cell range. */
3331
+ _chart_set_range(self->title.range, sheetname, row, col, row, col);
3332
+ }
3333
+
3334
+ /*
3335
+ * Set the chart title font.
3336
+ */
3337
+ void
3338
+ chart_title_set_name_font(lxw_chart *self, lxw_chart_font *font)
3339
+ {
3340
+ self->title.font = _chart_convert_font_args(font);
3341
+ }
3342
+
3343
+ /*
3344
+ * Turn off the chart title.
3345
+ */
3346
+ void
3347
+ chart_title_off(lxw_chart *self)
3348
+ {
3349
+ self->title.off = LXW_TRUE;
3350
+ }
3351
+
3352
+ /*
3353
+ * Set the chart legend position.
3354
+ */
3355
+ void
3356
+ chart_legend_set_position(lxw_chart *self, uint8_t position)
3357
+ {
3358
+ self->legend.position = position;
3359
+ }
3360
+
3361
+ /*
3362
+ * Set the legend font.
3363
+ */
3364
+ void
3365
+ chart_legend_set_font(lxw_chart *self, lxw_chart_font *font)
3366
+ {
3367
+ self->legend.font = _chart_convert_font_args(font);
3368
+ }
3369
+
3370
+ /*
3371
+ * Remove one or more series from the the legend.
3372
+ */
3373
+ lxw_error
3374
+ chart_legend_delete_series(lxw_chart *self, int16_t delete_series[])
3375
+ {
3376
+ uint16_t count = 0;
3377
+
3378
+ if (delete_series == NULL)
3379
+ return LXW_ERROR_NULL_PARAMETER_IGNORED;
3380
+
3381
+ while (delete_series[count] > 0)
3382
+ count++;
3383
+
3384
+ /* The maximum number of series in a chart is 255. */
3385
+ if (count > 255)
3386
+ count = 255;
3387
+
3388
+ self->delete_series = calloc(count, sizeof(int16_t));
3389
+ RETURN_ON_MEM_ERROR(self->delete_series, LXW_ERROR_MEMORY_MALLOC_FAILED);
3390
+ memcpy(self->delete_series, delete_series, count * sizeof(int16_t));
3391
+ self->delete_series_count = count;
3392
+
3393
+ return LXW_NO_ERROR;
3394
+ }
3395
+
3396
+ /*
3397
+ * Set the Pie/Doughnut chart rotation: the angle of the first slice.
3398
+ */
3399
+ void
3400
+ chart_set_rotation(lxw_chart *self, uint16_t rotation)
3401
+ {
3402
+ if (rotation <= 360)
3403
+ self->rotation = rotation;
3404
+ else
3405
+ LXW_WARN_FORMAT1("chart_set_rotation(): Chart rotation '%d' outside "
3406
+ "range: 0 <= rotation <= 360", rotation);
3407
+ }
3408
+
3409
+ /*
3410
+ * Set the Doughnut chart hole size.
3411
+ */
3412
+ void
3413
+ chart_set_hole_size(lxw_chart *self, uint8_t size)
3414
+ {
3415
+ if (size >= 10 && size <= 90)
3416
+ self->hole_size = size;
3417
+ else
3418
+ LXW_WARN_FORMAT1("chart_set_hole_size(): Hole size '%d' outside "
3419
+ "Excel range: 10 <= size <= 90", size);
3420
+ }