xlsxwriter 0.2.1.pre.2 → 0.2.3.pre.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (123) hide show
  1. checksums.yaml +4 -4
  2. data/Rakefile +4 -3
  3. data/ext/xlsxwriter/chart.c +84 -20
  4. data/ext/xlsxwriter/chart.h +1 -0
  5. data/ext/xlsxwriter/chartsheet.c +34 -13
  6. data/ext/xlsxwriter/common.h +5 -5
  7. data/ext/xlsxwriter/extconf.rb +8 -8
  8. data/ext/xlsxwriter/libxlsxwriter/License.txt +24 -2
  9. data/ext/xlsxwriter/libxlsxwriter/Makefile +46 -12
  10. data/ext/xlsxwriter/libxlsxwriter/include/xlsxwriter/app.h +1 -1
  11. data/ext/xlsxwriter/libxlsxwriter/include/xlsxwriter/chart.h +196 -30
  12. data/ext/xlsxwriter/libxlsxwriter/include/xlsxwriter/chartsheet.h +3 -3
  13. data/ext/xlsxwriter/libxlsxwriter/include/xlsxwriter/comment.h +76 -0
  14. data/ext/xlsxwriter/libxlsxwriter/include/xlsxwriter/common.h +24 -5
  15. data/ext/xlsxwriter/libxlsxwriter/include/xlsxwriter/content_types.h +5 -1
  16. data/ext/xlsxwriter/libxlsxwriter/include/xlsxwriter/core.h +1 -1
  17. data/ext/xlsxwriter/libxlsxwriter/include/xlsxwriter/custom.h +1 -1
  18. data/ext/xlsxwriter/libxlsxwriter/include/xlsxwriter/drawing.h +6 -17
  19. data/ext/xlsxwriter/libxlsxwriter/include/xlsxwriter/format.h +20 -6
  20. data/ext/xlsxwriter/libxlsxwriter/include/xlsxwriter/hash_table.h +1 -1
  21. data/ext/xlsxwriter/libxlsxwriter/include/xlsxwriter/packager.h +3 -1
  22. data/ext/xlsxwriter/libxlsxwriter/include/xlsxwriter/relationships.h +1 -1
  23. data/ext/xlsxwriter/libxlsxwriter/include/xlsxwriter/shared_strings.h +1 -1
  24. data/ext/xlsxwriter/libxlsxwriter/include/xlsxwriter/styles.h +11 -5
  25. data/ext/xlsxwriter/libxlsxwriter/include/xlsxwriter/theme.h +1 -1
  26. data/ext/xlsxwriter/libxlsxwriter/include/xlsxwriter/third_party/md5.h +43 -0
  27. data/ext/xlsxwriter/libxlsxwriter/include/xlsxwriter/utility.h +42 -3
  28. data/ext/xlsxwriter/libxlsxwriter/include/xlsxwriter/vml.h +55 -0
  29. data/ext/xlsxwriter/libxlsxwriter/include/xlsxwriter/workbook.h +83 -18
  30. data/ext/xlsxwriter/libxlsxwriter/include/xlsxwriter/worksheet.h +1519 -109
  31. data/ext/xlsxwriter/libxlsxwriter/include/xlsxwriter/xmlwriter.h +4 -2
  32. data/ext/xlsxwriter/libxlsxwriter/include/xlsxwriter.h +3 -2
  33. data/ext/xlsxwriter/libxlsxwriter/src/Makefile +25 -7
  34. data/ext/xlsxwriter/libxlsxwriter/src/app.c +1 -1
  35. data/ext/xlsxwriter/libxlsxwriter/src/chart.c +332 -48
  36. data/ext/xlsxwriter/libxlsxwriter/src/chartsheet.c +20 -19
  37. data/ext/xlsxwriter/libxlsxwriter/src/comment.c +443 -0
  38. data/ext/xlsxwriter/libxlsxwriter/src/content_types.c +20 -1
  39. data/ext/xlsxwriter/libxlsxwriter/src/core.c +2 -2
  40. data/ext/xlsxwriter/libxlsxwriter/src/custom.c +1 -1
  41. data/ext/xlsxwriter/libxlsxwriter/src/drawing.c +58 -20
  42. data/ext/xlsxwriter/libxlsxwriter/src/format.c +98 -25
  43. data/ext/xlsxwriter/libxlsxwriter/src/hash_table.c +1 -1
  44. data/ext/xlsxwriter/libxlsxwriter/src/packager.c +269 -12
  45. data/ext/xlsxwriter/libxlsxwriter/src/relationships.c +1 -1
  46. data/ext/xlsxwriter/libxlsxwriter/src/shared_strings.c +2 -4
  47. data/ext/xlsxwriter/libxlsxwriter/src/styles.c +334 -48
  48. data/ext/xlsxwriter/libxlsxwriter/src/theme.c +1 -1
  49. data/ext/xlsxwriter/libxlsxwriter/src/utility.c +71 -8
  50. data/ext/xlsxwriter/libxlsxwriter/src/vml.c +1032 -0
  51. data/ext/xlsxwriter/libxlsxwriter/src/workbook.c +343 -27
  52. data/ext/xlsxwriter/libxlsxwriter/src/worksheet.c +3759 -478
  53. data/ext/xlsxwriter/libxlsxwriter/src/xmlwriter.c +81 -2
  54. data/ext/xlsxwriter/libxlsxwriter/third_party/md5/Makefile +42 -0
  55. data/ext/xlsxwriter/libxlsxwriter/third_party/md5/md5.c +291 -0
  56. data/ext/xlsxwriter/libxlsxwriter/third_party/md5/md5.h +43 -0
  57. data/ext/xlsxwriter/rich_string.c +28 -9
  58. data/ext/xlsxwriter/shared_strings.c +75 -0
  59. data/ext/xlsxwriter/shared_strings.h +15 -0
  60. data/ext/xlsxwriter/workbook.c +87 -13
  61. data/ext/xlsxwriter/workbook.h +1 -0
  62. data/ext/xlsxwriter/workbook_properties.c +2 -2
  63. data/ext/xlsxwriter/worksheet.c +75 -23
  64. data/ext/xlsxwriter/worksheet.h +1 -0
  65. data/ext/xlsxwriter/xlsxwriter.c +2 -0
  66. data/lib/xlsxwriter/rich_string.rb +0 -2
  67. data/lib/xlsxwriter/version.rb +1 -1
  68. data/lib/xlsxwriter/worksheet.rb +2 -2
  69. data/test/{run-test.rb → run_test.rb} +3 -3
  70. data/test/support/chart_test.rb +3 -3
  71. data/test/support/with_xlsx_file.rb +4 -2
  72. data/test/support/xlsx_comparable.rb +40 -26
  73. data/test/test_array_formula.rb +42 -0
  74. data/test/test_autofilter.rb +72 -0
  75. data/test/{test-chart-area.rb → test_chart_area.rb} +2 -2
  76. data/test/{test-chart-axis.rb → test_chart_axis.rb} +16 -16
  77. data/test/test_chart_bar.rb +382 -0
  78. data/test/test_chart_blank.rb +27 -0
  79. data/test/{test-chart-column.rb → test_chart_column.rb} +2 -2
  80. data/test/{test-chart-doughnut.rb → test_chart_doughnut.rb} +2 -2
  81. data/test/{test-chart-legend.rb → test_chart_legend.rb} +2 -2
  82. data/test/{test-chart-pie.rb → test_chart_pie.rb} +2 -2
  83. data/test/{test-chart-scatter.rb → test_chart_scatter.rb} +3 -4
  84. data/test/{test-chart-size.rb → test_chart_size.rb} +2 -2
  85. data/test/{test-chart-title.rb → test_chart_title.rb} +3 -3
  86. data/test/{test-chartsheet.rb → test_chartsheet.rb} +2 -2
  87. data/test/{test-data.rb → test_data.rb} +1 -1
  88. data/test/{test-data-validation.rb → test_data_validation.rb} +23 -24
  89. data/test/{test-default-row.rb → test_default_row.rb} +1 -1
  90. data/test/{test-defined-name.rb → test_defined_name.rb} +12 -12
  91. data/test/{test-escapes.rb → test_escapes.rb} +5 -2
  92. data/test/{test-fit-to-pages.rb → test_fit_to_pages.rb} +6 -6
  93. data/test/{test-formatting.rb → test_formatting.rb} +10 -10
  94. data/test/{test-gridlines.rb → test_gridlines.rb} +3 -3
  95. data/test/{test-hyperlink.rb → test_hyperlink.rb} +22 -11
  96. data/test/{test-image.rb → test_image.rb} +6 -4
  97. data/test/{test-macro.rb → test_macro.rb} +1 -1
  98. data/test/{test-merge-range.rb → test_merge_range.rb} +1 -1
  99. data/test/{test-misc.rb → test_misc.rb} +2 -2
  100. data/test/{test-optimize.rb → test_optimize.rb} +2 -4
  101. data/test/{test-outline.rb → test_outline.rb} +14 -14
  102. data/test/{test-page-breaks.rb → test_page_breaks.rb} +2 -2
  103. data/test/{test-page-setup.rb → test_page_setup.rb} +2 -2
  104. data/test/{test-panes.rb → test_panes.rb} +1 -1
  105. data/test/{test-print-area.rb → test_print_area.rb} +3 -3
  106. data/test/{test-print-options.rb → test_print_options.rb} +7 -7
  107. data/test/{test-print-scale.rb → test_print_scale.rb} +2 -2
  108. data/test/{test-properties.rb → test_properties.rb} +2 -2
  109. data/test/{test-protect.rb → test_protect.rb} +3 -3
  110. data/test/{test-repeat.rb → test_repeat.rb} +3 -3
  111. data/test/{test-rich-string.rb → test_rich_string.rb} +5 -9
  112. data/test/{test-row-col-format.rb → test_row_col_format.rb} +1 -1
  113. data/test/{test-ruby-worksheet.rb → test_ruby_worksheet.rb} +2 -2
  114. data/test/{test-set-selection.rb → test_set_selection.rb} +2 -2
  115. data/test/{test-set-start-page.rb → test_set_start_page.rb} +2 -2
  116. data/test/{test-simple.rb → test_simple.rb} +10 -10
  117. data/test/{test-types.rb → test_types.rb} +1 -1
  118. data/test/{xlsx-func-testcase.rb → xlsx_func_testcase.rb} +1 -0
  119. metadata +127 -106
  120. data/test/test-array-formula.rb +0 -35
  121. data/test/test-autofilter.rb +0 -72
  122. data/test/test-chart-bar.rb +0 -74
  123. /data/test/{test-errors.rb → test_errors.rb} +0 -0
@@ -0,0 +1,1032 @@
1
+ /*****************************************************************************
2
+ * vml - A library for creating Excel XLSX vml files.
3
+ *
4
+ * Used in conjunction with the libxlsxwriter library.
5
+ *
6
+ * Copyright 2014-2020, John McNamara, jmcnamara@cpan.org. See LICENSE.txt.
7
+ *
8
+ */
9
+
10
+ #include "xlsxwriter/xmlwriter.h"
11
+ #include "xlsxwriter/vml.h"
12
+ #include "xlsxwriter/utility.h"
13
+
14
+ /*
15
+ * Forward declarations.
16
+ */
17
+
18
+ /*****************************************************************************
19
+ *
20
+ * Private functions.
21
+ *
22
+ ****************************************************************************/
23
+
24
+ /*
25
+ * Create a new vml object.
26
+ */
27
+ lxw_vml *
28
+ lxw_vml_new(void)
29
+ {
30
+ lxw_vml *vml = calloc(1, sizeof(lxw_vml));
31
+ GOTO_LABEL_ON_MEM_ERROR(vml, mem_error);
32
+
33
+ return vml;
34
+
35
+ mem_error:
36
+ lxw_vml_free(vml);
37
+ return NULL;
38
+ }
39
+
40
+ /*
41
+ * Free a vml object.
42
+ */
43
+ void
44
+ lxw_vml_free(lxw_vml *vml)
45
+ {
46
+ if (!vml)
47
+ return;
48
+
49
+ free(vml);
50
+ }
51
+
52
+ /*****************************************************************************
53
+ *
54
+ * XML functions.
55
+ *
56
+ ****************************************************************************/
57
+ /*
58
+ * Write the <x:Visible> element.
59
+ */
60
+ STATIC void
61
+ _vml_write_visible(lxw_vml *self)
62
+ {
63
+ lxw_xml_empty_tag(self->file, "x:Visible", NULL);
64
+ }
65
+
66
+ /*
67
+ * Write the <v:f> element.
68
+ */
69
+ STATIC void
70
+ _vml_write_formula(lxw_vml *self, char *equation)
71
+ {
72
+ struct xml_attribute_list attributes;
73
+ struct xml_attribute *attribute;
74
+
75
+ LXW_INIT_ATTRIBUTES();
76
+ LXW_PUSH_ATTRIBUTES_STR("eqn", equation);
77
+
78
+ lxw_xml_empty_tag(self->file, "v:f", &attributes);
79
+
80
+ LXW_FREE_ATTRIBUTES();
81
+ }
82
+
83
+ /*
84
+ * Write the <v:formulas> element.
85
+ */
86
+ STATIC void
87
+ _vml_write_formulas(lxw_vml *self)
88
+ {
89
+ lxw_xml_start_tag(self->file, "v:formulas", NULL);
90
+
91
+ _vml_write_formula(self, "if lineDrawn pixelLineWidth 0");
92
+ _vml_write_formula(self, "sum @0 1 0");
93
+ _vml_write_formula(self, "sum 0 0 @1");
94
+ _vml_write_formula(self, "prod @2 1 2");
95
+ _vml_write_formula(self, "prod @3 21600 pixelWidth");
96
+ _vml_write_formula(self, "prod @3 21600 pixelHeight");
97
+ _vml_write_formula(self, "sum @0 0 1");
98
+ _vml_write_formula(self, "prod @6 1 2");
99
+ _vml_write_formula(self, "prod @7 21600 pixelWidth");
100
+ _vml_write_formula(self, "sum @8 21600 0");
101
+ _vml_write_formula(self, "prod @7 21600 pixelHeight");
102
+ _vml_write_formula(self, "sum @10 21600 0");
103
+
104
+ lxw_xml_end_tag(self->file, "v:formulas");
105
+ }
106
+
107
+ /*
108
+ * Write the <x:TextHAlign> element.
109
+ */
110
+ STATIC void
111
+ _vml_write_text_halign(lxw_vml *self)
112
+ {
113
+
114
+ lxw_xml_data_element(self->file, "x:TextHAlign", "Center", NULL);
115
+ }
116
+
117
+ /*
118
+ * Write the <x:TextVAlign> element.
119
+ */
120
+ STATIC void
121
+ _vml_write_text_valign(lxw_vml *self)
122
+ {
123
+ lxw_xml_data_element(self->file, "x:TextVAlign", "Center", NULL);
124
+ }
125
+
126
+ /*
127
+ * Write the <x:FmlaMacro> element.
128
+ */
129
+ STATIC void
130
+ _vml_write_fmla_macro(lxw_vml *self)
131
+ {
132
+ lxw_xml_data_element(self->file, "x:FmlaMacro", "[0]!Button1_Click",
133
+ NULL);
134
+ }
135
+
136
+ /*
137
+ * Write the <x:PrintObject> element.
138
+ */
139
+ STATIC void
140
+ _vml_write_print_object(lxw_vml *self)
141
+ {
142
+ lxw_xml_data_element(self->file, "x:PrintObject", "False", NULL);
143
+ }
144
+
145
+ /*
146
+ * Write the <o:lock> element.
147
+ */
148
+ STATIC void
149
+ _vml_write_aspect_ratio_lock(lxw_vml *self)
150
+ {
151
+ struct xml_attribute_list attributes;
152
+ struct xml_attribute *attribute;
153
+
154
+ LXW_INIT_ATTRIBUTES();
155
+ LXW_PUSH_ATTRIBUTES_STR("v:ext", "edit");
156
+ LXW_PUSH_ATTRIBUTES_STR("aspectratio", "t");
157
+
158
+ lxw_xml_empty_tag(self->file, "o:lock", &attributes);
159
+
160
+ LXW_FREE_ATTRIBUTES();
161
+ }
162
+
163
+ /*
164
+ * Write the <o:lock> element.
165
+ */
166
+ STATIC void
167
+ _vml_write_rotation_lock(lxw_vml *self)
168
+ {
169
+ struct xml_attribute_list attributes;
170
+ struct xml_attribute *attribute;
171
+
172
+ LXW_INIT_ATTRIBUTES();
173
+ LXW_PUSH_ATTRIBUTES_STR("v:ext", "edit");
174
+ LXW_PUSH_ATTRIBUTES_STR("rotation", "t");
175
+
176
+ lxw_xml_empty_tag(self->file, "o:lock", &attributes);
177
+
178
+ LXW_FREE_ATTRIBUTES();
179
+ }
180
+
181
+ /*
182
+ * Write the <x:Column> element.
183
+ */
184
+ STATIC void
185
+ _vml_write_column(lxw_vml *self, lxw_vml_obj *comment_obj)
186
+ {
187
+ char data[LXW_ATTR_32];
188
+
189
+ lxw_snprintf(data, LXW_ATTR_32, "%d", comment_obj->col);
190
+
191
+ lxw_xml_data_element(self->file, "x:Column", data, NULL);
192
+ }
193
+
194
+ /*
195
+ * Write the <x:Row> element.
196
+ */
197
+ STATIC void
198
+ _vml_write_row(lxw_vml *self, lxw_vml_obj *comment_obj)
199
+ {
200
+ char data[LXW_ATTR_32];
201
+
202
+ lxw_snprintf(data, LXW_ATTR_32, "%d", comment_obj->row);
203
+
204
+ lxw_xml_data_element(self->file, "x:Row", data, NULL);
205
+ }
206
+
207
+ /*
208
+ * Write the <x:AutoFill> element.
209
+ */
210
+ STATIC void
211
+ _vml_write_auto_fill(lxw_vml *self)
212
+ {
213
+ lxw_xml_data_element(self->file, "x:AutoFill", "False", NULL);
214
+ }
215
+
216
+ /*
217
+ * Write the <x:Anchor> element.
218
+ */
219
+ STATIC void
220
+ _vml_write_anchor(lxw_vml *self, lxw_vml_obj *comment_obj)
221
+ {
222
+ char anchor_data[LXW_MAX_ATTRIBUTE_LENGTH];
223
+
224
+ lxw_snprintf(anchor_data,
225
+ LXW_MAX_ATTRIBUTE_LENGTH,
226
+ "%d, %d, %d, %d, %d, %d, %d, %d",
227
+ comment_obj->from.col,
228
+ (uint32_t) comment_obj->from.col_offset,
229
+ comment_obj->from.row,
230
+ (uint32_t) comment_obj->from.row_offset,
231
+ comment_obj->to.col,
232
+ (uint32_t) comment_obj->to.col_offset,
233
+ comment_obj->to.row, (uint32_t) comment_obj->to.row_offset);
234
+
235
+ lxw_xml_data_element(self->file, "x:Anchor", anchor_data, NULL);
236
+ }
237
+
238
+ /*
239
+ * Write the <x:SizeWithCells> element.
240
+ */
241
+ STATIC void
242
+ _vml_write_size_with_cells(lxw_vml *self)
243
+ {
244
+ lxw_xml_empty_tag(self->file, "x:SizeWithCells", NULL);
245
+ }
246
+
247
+ /*
248
+ * Write the <x:MoveWithCells> element.
249
+ */
250
+ STATIC void
251
+ _vml_write_move_with_cells(lxw_vml *self)
252
+ {
253
+ lxw_xml_empty_tag(self->file, "x:MoveWithCells", NULL);
254
+ }
255
+
256
+ /*
257
+ * Write the <v:shadow> element.
258
+ */
259
+ STATIC void
260
+ _vml_write_shadow(lxw_vml *self)
261
+ {
262
+ struct xml_attribute_list attributes;
263
+ struct xml_attribute *attribute;
264
+
265
+ LXW_INIT_ATTRIBUTES();
266
+ LXW_PUSH_ATTRIBUTES_STR("on", "t");
267
+ LXW_PUSH_ATTRIBUTES_STR("color", "black");
268
+ LXW_PUSH_ATTRIBUTES_STR("obscured", "t");
269
+
270
+ lxw_xml_empty_tag(self->file, "v:shadow", &attributes);
271
+
272
+ LXW_FREE_ATTRIBUTES();
273
+ }
274
+
275
+ /*
276
+ * Write the <v:stroke> element.
277
+ */
278
+ STATIC void
279
+ _vml_write_stroke(lxw_vml *self)
280
+ {
281
+ struct xml_attribute_list attributes;
282
+ struct xml_attribute *attribute;
283
+
284
+ LXW_INIT_ATTRIBUTES();
285
+ LXW_PUSH_ATTRIBUTES_STR("joinstyle", "miter");
286
+
287
+ lxw_xml_empty_tag(self->file, "v:stroke", &attributes);
288
+
289
+ LXW_FREE_ATTRIBUTES();
290
+ }
291
+
292
+ /*
293
+ * Write the <o:lock> element.
294
+ */
295
+ STATIC void
296
+ _vml_write_shapetype_lock(lxw_vml *self)
297
+ {
298
+ struct xml_attribute_list attributes;
299
+ struct xml_attribute *attribute;
300
+
301
+ LXW_INIT_ATTRIBUTES();
302
+ LXW_PUSH_ATTRIBUTES_STR("v:ext", "edit");
303
+ LXW_PUSH_ATTRIBUTES_STR("shapetype", "t");
304
+
305
+ lxw_xml_empty_tag(self->file, "o:lock", &attributes);
306
+
307
+ LXW_FREE_ATTRIBUTES();
308
+ }
309
+
310
+ /*
311
+ * Write the <font> element.
312
+ */
313
+ STATIC void
314
+ _vml_write_font(lxw_vml *self)
315
+ {
316
+ struct xml_attribute_list attributes;
317
+ struct xml_attribute *attribute;
318
+
319
+ LXW_INIT_ATTRIBUTES();
320
+ LXW_PUSH_ATTRIBUTES_STR("face", "Calibri");
321
+ LXW_PUSH_ATTRIBUTES_STR("size", "220");
322
+ LXW_PUSH_ATTRIBUTES_STR("color", "#000000");
323
+
324
+ lxw_xml_data_element(self->file, "font", "Button 1", &attributes);
325
+
326
+ LXW_FREE_ATTRIBUTES();
327
+ }
328
+
329
+ /*
330
+ * Write the <v:imagedata> element.
331
+ */
332
+ STATIC void
333
+ _vml_write_imagedata(lxw_vml *self, uint32_t rel_index, char *name)
334
+ {
335
+ struct xml_attribute_list attributes;
336
+ struct xml_attribute *attribute;
337
+ char rel_id[LXW_ATTR_32];
338
+
339
+ lxw_snprintf(rel_id, LXW_ATTR_32, "rId%d", rel_index);
340
+
341
+ LXW_INIT_ATTRIBUTES();
342
+ LXW_PUSH_ATTRIBUTES_STR("o:relid", rel_id);
343
+ LXW_PUSH_ATTRIBUTES_STR("o:title", name);
344
+
345
+ lxw_xml_empty_tag(self->file, "v:imagedata", &attributes);
346
+
347
+ LXW_FREE_ATTRIBUTES();
348
+ }
349
+
350
+ /*
351
+ * Write the <v:path> element.
352
+ */
353
+ STATIC void
354
+ _vml_write_image_path(lxw_vml *self)
355
+ {
356
+ struct xml_attribute_list attributes;
357
+ struct xml_attribute *attribute;
358
+
359
+ LXW_INIT_ATTRIBUTES();
360
+ LXW_PUSH_ATTRIBUTES_STR("o:extrusionok", "f");
361
+ LXW_PUSH_ATTRIBUTES_STR("gradientshapeok", "t");
362
+ LXW_PUSH_ATTRIBUTES_STR("o:connecttype", "rect");
363
+
364
+ lxw_xml_empty_tag(self->file, "v:path", &attributes);
365
+
366
+ LXW_FREE_ATTRIBUTES();
367
+ }
368
+
369
+ /*
370
+ * Write the <v:shape> element.
371
+ */
372
+ STATIC void
373
+ _vml_write_image_shape(lxw_vml *self, uint32_t vml_shape_id, uint32_t z_index,
374
+ lxw_vml_obj *image_obj)
375
+ {
376
+ struct xml_attribute_list attributes;
377
+ struct xml_attribute *attribute;
378
+ char width_str[LXW_ATTR_32];
379
+ char height_str[LXW_ATTR_32];
380
+ char style[LXW_MAX_ATTRIBUTE_LENGTH];
381
+ char o_spid[LXW_ATTR_32];
382
+ char type[] = "#_x0000_t75";
383
+ double width;
384
+ double height;
385
+
386
+ /* Scale the height/width by the resolution, relative to 72dpi. */
387
+ width = image_obj->width * (72.0 / image_obj->x_dpi);
388
+ height = image_obj->height * (72.0 / image_obj->y_dpi);
389
+
390
+ /* Excel uses a rounding based around 72 and 96 dpi. */
391
+ width = 72.0 / 96.0 * (uint32_t) (width * 96.0 / 72 + 0.25);
392
+ height = 72.0 / 96.0 * (uint32_t) (height * 96.0 / 72 + 0.25);
393
+
394
+ lxw_sprintf_dbl(width_str, width);
395
+ lxw_sprintf_dbl(height_str, height);
396
+
397
+ lxw_snprintf(o_spid, LXW_ATTR_32, "_x0000_s%d", vml_shape_id);
398
+
399
+ lxw_snprintf(style,
400
+ LXW_MAX_ATTRIBUTE_LENGTH,
401
+ "position:absolute;"
402
+ "margin-left:0;"
403
+ "margin-top:0;"
404
+ "width:%spt;"
405
+ "height:%spt;" "z-index:%d", width_str, height_str, z_index);
406
+
407
+ LXW_INIT_ATTRIBUTES();
408
+ LXW_PUSH_ATTRIBUTES_STR("id", image_obj->image_position);
409
+ LXW_PUSH_ATTRIBUTES_STR("o:spid", o_spid);
410
+ LXW_PUSH_ATTRIBUTES_STR("type", type);
411
+ LXW_PUSH_ATTRIBUTES_STR("style", style);
412
+
413
+ lxw_xml_start_tag(self->file, "v:shape", &attributes);
414
+
415
+ /* Write the v:imagedata element. */
416
+ _vml_write_imagedata(self, image_obj->rel_index, image_obj->name);
417
+
418
+ /* Write the o:lock element. */
419
+ _vml_write_rotation_lock(self);
420
+
421
+ lxw_xml_end_tag(self->file, "v:shape");
422
+
423
+ LXW_FREE_ATTRIBUTES();
424
+ }
425
+
426
+ /*
427
+ * Write the <v:shapetype> element for images.
428
+ */
429
+ STATIC void
430
+ _vml_write_image_shapetype(lxw_vml *self)
431
+ {
432
+ struct xml_attribute_list attributes;
433
+ struct xml_attribute *attribute;
434
+ char id[] = "_x0000_t75";
435
+ char coordsize[] = "21600,21600";
436
+ char o_spt[] = "75";
437
+ char o_preferrelative[] = "t";
438
+ char path[] = "m@4@5l@4@11@9@11@9@5xe";
439
+ char filled[] = "f";
440
+ char stroked[] = "f";
441
+
442
+ LXW_INIT_ATTRIBUTES();
443
+ LXW_PUSH_ATTRIBUTES_STR("id", id);
444
+ LXW_PUSH_ATTRIBUTES_STR("coordsize", coordsize);
445
+ LXW_PUSH_ATTRIBUTES_STR("o:spt", o_spt);
446
+ LXW_PUSH_ATTRIBUTES_STR("o:preferrelative", o_preferrelative);
447
+ LXW_PUSH_ATTRIBUTES_STR("path", path);
448
+ LXW_PUSH_ATTRIBUTES_STR("filled", filled);
449
+ LXW_PUSH_ATTRIBUTES_STR("stroked", stroked);
450
+
451
+ lxw_xml_start_tag(self->file, "v:shapetype", &attributes);
452
+
453
+ /* Write the v:stroke element. */
454
+ _vml_write_stroke(self);
455
+
456
+ /* Write the v:formulas element. */
457
+ _vml_write_formulas(self);
458
+
459
+ /* Write the v:path element. */
460
+ _vml_write_image_path(self);
461
+
462
+ /* Write the o:lock element. */
463
+ _vml_write_aspect_ratio_lock(self);
464
+
465
+ lxw_xml_end_tag(self->file, "v:shapetype");
466
+
467
+ LXW_FREE_ATTRIBUTES();
468
+ }
469
+
470
+ /*
471
+ * Write the <x:ClientData> element.
472
+ */
473
+ STATIC void
474
+ _vml_write_button_client_data(lxw_vml *self)
475
+ {
476
+ struct xml_attribute_list attributes;
477
+ struct xml_attribute *attribute;
478
+
479
+ LXW_INIT_ATTRIBUTES();
480
+ LXW_PUSH_ATTRIBUTES_STR("ObjectType", "Button");
481
+
482
+ lxw_xml_start_tag(self->file, "x:ClientData", &attributes);
483
+
484
+ /* Write the <x:Anchor> element. */
485
+ _vml_write_anchor(self, NULL);
486
+
487
+ /* Write the x:PrintObject element. */
488
+ _vml_write_print_object(self);
489
+
490
+ /* Write the x:AutoFill element. */
491
+ _vml_write_auto_fill(self);
492
+
493
+ /* Write the x:FmlaMacro element. */
494
+ _vml_write_fmla_macro(self);
495
+
496
+ /* Write the x:TextHAlign element. */
497
+ _vml_write_text_halign(self);
498
+
499
+ /* Write the x:TextVAlign element. */
500
+ _vml_write_text_valign(self);
501
+
502
+ lxw_xml_end_tag(self->file, "x:ClientData");
503
+
504
+ LXW_FREE_ATTRIBUTES();
505
+ }
506
+
507
+ /*
508
+ * Write the <div> element.
509
+ */
510
+ STATIC void
511
+ _vml_write_button_div(lxw_vml *self)
512
+ {
513
+ struct xml_attribute_list attributes;
514
+ struct xml_attribute *attribute;
515
+
516
+ LXW_INIT_ATTRIBUTES();
517
+ LXW_PUSH_ATTRIBUTES_STR("style", "text-align:center");
518
+
519
+ lxw_xml_start_tag(self->file, "div", &attributes);
520
+
521
+ /* Write the font element. */
522
+ _vml_write_font(self);
523
+
524
+ lxw_xml_end_tag(self->file, "div");
525
+
526
+ LXW_FREE_ATTRIBUTES();
527
+ }
528
+
529
+ /*
530
+ * Write the <v:textbox> element.
531
+ */
532
+ STATIC void
533
+ _vml_write_button_textbox(lxw_vml *self)
534
+ {
535
+ struct xml_attribute_list attributes;
536
+ struct xml_attribute *attribute;
537
+
538
+ LXW_INIT_ATTRIBUTES();
539
+ LXW_PUSH_ATTRIBUTES_STR("style", "mso-direction-alt:auto");
540
+ LXW_PUSH_ATTRIBUTES_STR("o:singleclick", "f");
541
+
542
+ lxw_xml_start_tag(self->file, "v:textbox", &attributes);
543
+
544
+ /* Write the div element. */
545
+ _vml_write_button_div(self);
546
+
547
+ lxw_xml_end_tag(self->file, "v:textbox");
548
+
549
+ LXW_FREE_ATTRIBUTES();
550
+ }
551
+
552
+ /*
553
+ * Write the <v:fill> element.
554
+ */
555
+ STATIC void
556
+ _vml_write_button_fill(lxw_vml *self)
557
+ {
558
+ struct xml_attribute_list attributes;
559
+ struct xml_attribute *attribute;
560
+
561
+ LXW_INIT_ATTRIBUTES();
562
+ LXW_PUSH_ATTRIBUTES_STR("color2", "buttonFace [67]");
563
+ LXW_PUSH_ATTRIBUTES_STR("o:detectmouseclick", "t");
564
+
565
+ lxw_xml_empty_tag(self->file, "v:fill", &attributes);
566
+
567
+ LXW_FREE_ATTRIBUTES();
568
+ }
569
+
570
+ /*
571
+ * Write the <v:path> element for buttons.
572
+ */
573
+ STATIC void
574
+ _vml_write_button_path(lxw_vml *self)
575
+ {
576
+ struct xml_attribute_list attributes;
577
+ struct xml_attribute *attribute;
578
+
579
+ LXW_INIT_ATTRIBUTES();
580
+ LXW_PUSH_ATTRIBUTES_STR("shadowok", "f");
581
+ LXW_PUSH_ATTRIBUTES_STR("o:extrusionok", "f");
582
+ LXW_PUSH_ATTRIBUTES_STR("strokeok", "f");
583
+ LXW_PUSH_ATTRIBUTES_STR("fillok", "f");
584
+ LXW_PUSH_ATTRIBUTES_STR("o:connecttype", "rect");
585
+
586
+ lxw_xml_empty_tag(self->file, "v:path", &attributes);
587
+
588
+ LXW_FREE_ATTRIBUTES();
589
+ }
590
+
591
+ /*
592
+ * Write the <v:shape> element for buttons.
593
+ */
594
+ STATIC void
595
+ _vml_write_button_shape(lxw_vml *self)
596
+ {
597
+ struct xml_attribute_list attributes;
598
+ struct xml_attribute *attribute;
599
+ char id[] = "_x0000_s1025";
600
+ char type[] = "#_x0000_t201";
601
+ char style[] = "position:absolute;margin-left:96pt;margin-top:15pt;"
602
+ "width:48pt;height:15pt;z-index:1;mso-wrap-style:tight";
603
+ char o_button[] = "t";
604
+ char fillcolor[] = "buttonFace [67]";
605
+ char strokecolor[] = "windowText [64]";
606
+ char o_insetmode[] = "auto";
607
+
608
+ LXW_INIT_ATTRIBUTES();
609
+ LXW_PUSH_ATTRIBUTES_STR("id", id);
610
+ LXW_PUSH_ATTRIBUTES_STR("type", type);
611
+ LXW_PUSH_ATTRIBUTES_STR("style", style);
612
+ LXW_PUSH_ATTRIBUTES_STR("o:button", o_button);
613
+ LXW_PUSH_ATTRIBUTES_STR("fillcolor", fillcolor);
614
+ LXW_PUSH_ATTRIBUTES_STR("strokecolor", strokecolor);
615
+ LXW_PUSH_ATTRIBUTES_STR("o:insetmode", o_insetmode);
616
+
617
+ lxw_xml_start_tag(self->file, "v:shape", &attributes);
618
+
619
+ /* Write the v:fill element. */
620
+ _vml_write_button_fill(self);
621
+
622
+ /* Write the o:lock element. */
623
+ _vml_write_rotation_lock(self);
624
+
625
+ /* Write the v:textbox element. */
626
+ _vml_write_button_textbox(self);
627
+
628
+ /* Write the x:ClientData element. */
629
+ _vml_write_button_client_data(self);
630
+
631
+ lxw_xml_end_tag(self->file, "v:shape");
632
+
633
+ LXW_FREE_ATTRIBUTES();
634
+ }
635
+
636
+ /*
637
+ * Write the <v:shapetype> element for buttons.
638
+ */
639
+ STATIC void
640
+ _vml_write_button_shapetype(lxw_vml *self)
641
+ {
642
+ struct xml_attribute_list attributes;
643
+ struct xml_attribute *attribute;
644
+ char id[] = "_x0000_t201";
645
+ char coordsize[] = "21600,21600";
646
+ char o_spt[] = "201";
647
+ char path[] = "m,l,21600r21600,l21600,xe";
648
+
649
+ LXW_INIT_ATTRIBUTES();
650
+ LXW_PUSH_ATTRIBUTES_STR("id", id);
651
+ LXW_PUSH_ATTRIBUTES_STR("coordsize", coordsize);
652
+ LXW_PUSH_ATTRIBUTES_STR("o:spt", o_spt);
653
+ LXW_PUSH_ATTRIBUTES_STR("path", path);
654
+
655
+ lxw_xml_start_tag(self->file, "v:shapetype", &attributes);
656
+
657
+ /* Write the v:stroke element. */
658
+ _vml_write_stroke(self);
659
+
660
+ /* Write the v:path element. */
661
+ _vml_write_button_path(self);
662
+
663
+ /* Write the o:lock element. */
664
+ _vml_write_shapetype_lock(self);
665
+
666
+ lxw_xml_end_tag(self->file, "v:shapetype");
667
+
668
+ LXW_FREE_ATTRIBUTES();
669
+ }
670
+
671
+ /*
672
+ * Write the <x:ClientData> element.
673
+ */
674
+ STATIC void
675
+ _vml_write_comment_client_data(lxw_vml *self, lxw_vml_obj *comment_obj)
676
+ {
677
+ struct xml_attribute_list attributes;
678
+ struct xml_attribute *attribute;
679
+
680
+ LXW_INIT_ATTRIBUTES();
681
+ LXW_PUSH_ATTRIBUTES_STR("ObjectType", "Note");
682
+
683
+ lxw_xml_start_tag(self->file, "x:ClientData", &attributes);
684
+
685
+ /* Write the <x:MoveWithCells> element. */
686
+ _vml_write_move_with_cells(self);
687
+
688
+ /* Write the <x:SizeWithCells> element. */
689
+ _vml_write_size_with_cells(self);
690
+
691
+ /* Write the <x:Anchor> element. */
692
+ _vml_write_anchor(self, comment_obj);
693
+
694
+ /* Write the <x:AutoFill> element. */
695
+ _vml_write_auto_fill(self);
696
+
697
+ /* Write the <x:Row> element. */
698
+ _vml_write_row(self, comment_obj);
699
+
700
+ /* Write the <x:Column> element. */
701
+ _vml_write_column(self, comment_obj);
702
+
703
+ /* Write the x:Visible element. */
704
+ if (comment_obj->visible == LXW_COMMENT_DISPLAY_VISIBLE)
705
+ _vml_write_visible(self);
706
+
707
+ lxw_xml_end_tag(self->file, "x:ClientData");
708
+
709
+ LXW_FREE_ATTRIBUTES();
710
+ }
711
+
712
+ /*
713
+ * Write the <div> element.
714
+ */
715
+ STATIC void
716
+ _vml_write_comment_div(lxw_vml *self)
717
+ {
718
+ struct xml_attribute_list attributes;
719
+ struct xml_attribute *attribute;
720
+
721
+ LXW_INIT_ATTRIBUTES();
722
+ LXW_PUSH_ATTRIBUTES_STR("style", "text-align:left");
723
+
724
+ lxw_xml_start_tag(self->file, "div", &attributes);
725
+
726
+ lxw_xml_end_tag(self->file, "div");
727
+
728
+ LXW_FREE_ATTRIBUTES();
729
+ }
730
+
731
+ /*
732
+ * Write the <v:textbox> element.
733
+ */
734
+ STATIC void
735
+ _vml_write_comment_textbox(lxw_vml *self)
736
+ {
737
+ struct xml_attribute_list attributes;
738
+ struct xml_attribute *attribute;
739
+
740
+ LXW_INIT_ATTRIBUTES();
741
+ LXW_PUSH_ATTRIBUTES_STR("style", "mso-direction-alt:auto");
742
+
743
+ lxw_xml_start_tag(self->file, "v:textbox", &attributes);
744
+
745
+ /* Write the div element. */
746
+ _vml_write_comment_div(self);
747
+
748
+ lxw_xml_end_tag(self->file, "v:textbox");
749
+
750
+ LXW_FREE_ATTRIBUTES();
751
+ }
752
+
753
+ /*
754
+ * Write the <v:fill> element.
755
+ */
756
+ STATIC void
757
+ _vml_write_comment_fill(lxw_vml *self)
758
+ {
759
+ struct xml_attribute_list attributes;
760
+ struct xml_attribute *attribute;
761
+
762
+ LXW_INIT_ATTRIBUTES();
763
+ LXW_PUSH_ATTRIBUTES_STR("color2", "#ffffe1");
764
+
765
+ lxw_xml_empty_tag(self->file, "v:fill", &attributes);
766
+
767
+ LXW_FREE_ATTRIBUTES();
768
+ }
769
+
770
+ /*
771
+ * Write the <v:path> element.
772
+ */
773
+ STATIC void
774
+ _vml_write_comment_path(lxw_vml *self, uint8_t has_gradient, char *type)
775
+ {
776
+ struct xml_attribute_list attributes;
777
+ struct xml_attribute *attribute;
778
+
779
+ LXW_INIT_ATTRIBUTES();
780
+
781
+ if (has_gradient)
782
+ LXW_PUSH_ATTRIBUTES_STR("gradientshapeok", "t");
783
+
784
+ LXW_PUSH_ATTRIBUTES_STR("o:connecttype", type);
785
+
786
+ lxw_xml_empty_tag(self->file, "v:path", &attributes);
787
+
788
+ LXW_FREE_ATTRIBUTES();
789
+ }
790
+
791
+ /*
792
+ * Write the <v:shape> element for comments.
793
+ */
794
+ STATIC void
795
+ _vml_write_comment_shape(lxw_vml *self, uint32_t vml_shape_id,
796
+ uint32_t z_index, lxw_vml_obj *comment_obj)
797
+ {
798
+ struct xml_attribute_list attributes;
799
+ struct xml_attribute *attribute;
800
+ char id[LXW_ATTR_32];
801
+ char margin_left[LXW_ATTR_32];
802
+ char margin_top[LXW_ATTR_32];
803
+ char width[LXW_ATTR_32];
804
+ char height[LXW_ATTR_32];
805
+ char visible[LXW_ATTR_32];
806
+ char fillcolor[LXW_ATTR_32];
807
+ char style[LXW_MAX_ATTRIBUTE_LENGTH];
808
+ char type[] = "#_x0000_t202";
809
+ char o_insetmode[] = "auto";
810
+
811
+ lxw_sprintf_dbl(margin_left, comment_obj->col_absolute * 0.75);
812
+ lxw_sprintf_dbl(margin_top, comment_obj->row_absolute * 0.75);
813
+ lxw_sprintf_dbl(width, comment_obj->width * 0.75);
814
+ lxw_sprintf_dbl(height, comment_obj->height * 0.75);
815
+
816
+ lxw_snprintf(id, LXW_ATTR_32, "_x0000_s%d", vml_shape_id);
817
+
818
+ if (comment_obj->visible == LXW_COMMENT_DISPLAY_DEFAULT)
819
+ comment_obj->visible = self->comment_display_default;
820
+
821
+ if (comment_obj->visible == LXW_COMMENT_DISPLAY_VISIBLE)
822
+ lxw_snprintf(visible, LXW_ATTR_32, "visible");
823
+ else
824
+ lxw_snprintf(visible, LXW_ATTR_32, "hidden");
825
+
826
+ if (comment_obj->color)
827
+ lxw_snprintf(fillcolor, LXW_ATTR_32, "#%06x",
828
+ comment_obj->color & LXW_COLOR_MASK);
829
+ else
830
+ lxw_snprintf(fillcolor, LXW_ATTR_32, "#%06x", 0xffffe1);
831
+
832
+ lxw_snprintf(style,
833
+ LXW_MAX_ATTRIBUTE_LENGTH,
834
+ "position:absolute;"
835
+ "margin-left:%spt;"
836
+ "margin-top:%spt;"
837
+ "width:%spt;"
838
+ "height:%spt;"
839
+ "z-index:%d;"
840
+ "visibility:%s",
841
+ margin_left, margin_top, width, height, z_index, visible);
842
+
843
+ LXW_INIT_ATTRIBUTES();
844
+ LXW_PUSH_ATTRIBUTES_STR("id", id);
845
+ LXW_PUSH_ATTRIBUTES_STR("type", type);
846
+ LXW_PUSH_ATTRIBUTES_STR("style", style);
847
+ LXW_PUSH_ATTRIBUTES_STR("fillcolor", fillcolor);
848
+ LXW_PUSH_ATTRIBUTES_STR("o:insetmode", o_insetmode);
849
+
850
+ lxw_xml_start_tag(self->file, "v:shape", &attributes);
851
+
852
+ /* Write the v:fill element. */
853
+ _vml_write_comment_fill(self);
854
+
855
+ /* Write the v:shadow element. */
856
+ _vml_write_shadow(self);
857
+
858
+ /* Write the v:path element. */
859
+ _vml_write_comment_path(self, LXW_FALSE, "none");
860
+
861
+ /* Write the v:textbox element. */
862
+ _vml_write_comment_textbox(self);
863
+
864
+ /* Write the x:ClientData element. */
865
+ _vml_write_comment_client_data(self, comment_obj);
866
+
867
+ lxw_xml_end_tag(self->file, "v:shape");
868
+
869
+ LXW_FREE_ATTRIBUTES();
870
+ }
871
+
872
+ /*
873
+ * Write the <v:shapetype> element for comments.
874
+ */
875
+ STATIC void
876
+ _vml_write_comment_shapetype(lxw_vml *self)
877
+ {
878
+ struct xml_attribute_list attributes;
879
+ struct xml_attribute *attribute;
880
+ char id[] = "_x0000_t202";
881
+ char coordsize[] = "21600,21600";
882
+ char o_spt[] = "202";
883
+ char path[] = "m,l,21600r21600,l21600,xe";
884
+
885
+ LXW_INIT_ATTRIBUTES();
886
+ LXW_PUSH_ATTRIBUTES_STR("id", id);
887
+ LXW_PUSH_ATTRIBUTES_STR("coordsize", coordsize);
888
+ LXW_PUSH_ATTRIBUTES_STR("o:spt", o_spt);
889
+ LXW_PUSH_ATTRIBUTES_STR("path", path);
890
+
891
+ lxw_xml_start_tag(self->file, "v:shapetype", &attributes);
892
+
893
+ /* Write the v:stroke element. */
894
+ _vml_write_stroke(self);
895
+
896
+ /* Write the v:path element. */
897
+ _vml_write_comment_path(self, LXW_TRUE, "rect");
898
+
899
+ lxw_xml_end_tag(self->file, "v:shapetype");
900
+
901
+ LXW_FREE_ATTRIBUTES();
902
+ }
903
+
904
+ /*
905
+ * Write the <o:idmap> element.
906
+ */
907
+ STATIC void
908
+ _vml_write_idmap(lxw_vml *self)
909
+ {
910
+ /* Since the vml_data_id_str may exceed the LXW_MAX_ATTRIBUTE_LENGTH we
911
+ * write it directly without the xml helper functions. */
912
+ fprintf(self->file, "<o:idmap v:ext=\"edit\" data=\"%s\"/>",
913
+ self->vml_data_id_str);
914
+ }
915
+
916
+ /*
917
+ * Write the <o:shapelayout> element.
918
+ */
919
+ STATIC void
920
+ _vml_write_shapelayout(lxw_vml *self)
921
+ {
922
+ struct xml_attribute_list attributes;
923
+ struct xml_attribute *attribute;
924
+
925
+ LXW_INIT_ATTRIBUTES();
926
+ LXW_PUSH_ATTRIBUTES_STR("v:ext", "edit");
927
+
928
+ lxw_xml_start_tag(self->file, "o:shapelayout", &attributes);
929
+
930
+ /* Write the o:idmap element. */
931
+ _vml_write_idmap(self);
932
+
933
+ lxw_xml_end_tag(self->file, "o:shapelayout");
934
+
935
+ LXW_FREE_ATTRIBUTES();
936
+ }
937
+
938
+ /*
939
+ * Write the <xml> element.
940
+ */
941
+ STATIC void
942
+ _vml_write_xml_namespace(lxw_vml *self)
943
+ {
944
+ struct xml_attribute_list attributes;
945
+ struct xml_attribute *attribute;
946
+ char xmlns_v[] = "urn:schemas-microsoft-com:vml";
947
+ char xmlns_o[] = "urn:schemas-microsoft-com:office:office";
948
+ char xmlns_x[] = "urn:schemas-microsoft-com:office:excel";
949
+
950
+ LXW_INIT_ATTRIBUTES();
951
+ LXW_PUSH_ATTRIBUTES_STR("xmlns:v", xmlns_v);
952
+ LXW_PUSH_ATTRIBUTES_STR("xmlns:o", xmlns_o);
953
+ LXW_PUSH_ATTRIBUTES_STR("xmlns:x", xmlns_x);
954
+
955
+ lxw_xml_start_tag(self->file, "xml", &attributes);
956
+
957
+ LXW_FREE_ATTRIBUTES();
958
+ }
959
+
960
+ /*****************************************************************************
961
+ *
962
+ * XML file assembly functions.
963
+ *
964
+ ****************************************************************************/
965
+
966
+ /*
967
+ * Assemble and write the XML file.
968
+ */
969
+ void
970
+ lxw_vml_assemble_xml_file(lxw_vml *self)
971
+ {
972
+ lxw_vml_obj *comment_obj;
973
+ lxw_vml_obj *button_obj;
974
+ lxw_vml_obj *image_obj;
975
+ uint32_t z_index = 1;
976
+
977
+ /* Write the xml namespace element. Note, the VML files have no
978
+ * XML declaration.*/
979
+ _vml_write_xml_namespace(self);
980
+
981
+ /* Write the o:shapelayout element. */
982
+ _vml_write_shapelayout(self);
983
+
984
+ if (self->comment_objs) {
985
+ /* Write the <v:shapetype> element. */
986
+ _vml_write_comment_shapetype(self);
987
+
988
+ STAILQ_FOREACH(comment_obj, self->comment_objs, list_pointers) {
989
+ self->vml_shape_id++;
990
+
991
+ /* Write the <v:shape> element. */
992
+ _vml_write_comment_shape(self, self->vml_shape_id, z_index,
993
+ comment_obj);
994
+
995
+ z_index++;
996
+ }
997
+ }
998
+
999
+ if (self->button_objs) {
1000
+ /* Write the <v:shapetype> element. */
1001
+ _vml_write_button_shapetype(self);
1002
+
1003
+ STAILQ_FOREACH(button_obj, self->button_objs, list_pointers) {
1004
+ /* Write the <v:shape> element. */
1005
+ _vml_write_button_shape(self);
1006
+
1007
+ }
1008
+ }
1009
+
1010
+ if (self->image_objs) {
1011
+ /* Write the <v:shapetype> element. */
1012
+ _vml_write_image_shapetype(self);
1013
+
1014
+ STAILQ_FOREACH(image_obj, self->image_objs, list_pointers) {
1015
+ self->vml_shape_id++;
1016
+
1017
+ /* Write the <v:shape> element. */
1018
+ _vml_write_image_shape(self, self->vml_shape_id, z_index,
1019
+ image_obj);
1020
+
1021
+ z_index++;
1022
+ }
1023
+ }
1024
+
1025
+ lxw_xml_end_tag(self->file, "xml");
1026
+ }
1027
+
1028
+ /*****************************************************************************
1029
+ *
1030
+ * Public functions.
1031
+ *
1032
+ ****************************************************************************/