fast_excel 0.4.1 → 0.5.0

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