libxlsxwriter/src/drawing.c in fast_excel-0.4.1 vs libxlsxwriter/src/drawing.c in fast_excel-0.5.0

- old
+ new

@@ -1,17 +1,18 @@ /***************************************************************************** * drawing - A library for creating Excel XLSX drawing files. * * Used in conjunction with the libxlsxwriter library. * - * Copyright 2014-2019, John McNamara, jmcnamara@cpan.org. See LICENSE.txt. + * Copyright 2014-2022, John McNamara, jmcnamara@cpan.org. See LICENSE.txt. * */ #include "xlsxwriter/xmlwriter.h" #include "xlsxwriter/common.h" #include "xlsxwriter/drawing.h" +#include "xlsxwriter/worksheet.h" #include "xlsxwriter/utility.h" #define LXW_OBJ_NAME_LENGTH 14 /* "Picture 65536", or "Chart 65536" */ /* * Forward declarations. @@ -52,11 +53,10 @@ { if (!drawing_object) return; free(drawing_object->description); - free(drawing_object->url); free(drawing_object->tip); free(drawing_object); } @@ -166,19 +166,17 @@ { lxw_xml_data_element(self->file, "xdr:rowOff", data, NULL); } /* - * Write the <xdr:from> element. + * Write the main part of the <xdr:from> and <xdr:to> elements. */ STATIC void -_drawing_write_from(lxw_drawing *self, lxw_drawing_coords *coords) +_drawing_write_coords(lxw_drawing *self, lxw_drawing_coords *coords) { char data[LXW_UINT32_T_LENGTH]; - lxw_xml_start_tag(self->file, "xdr:from", NULL); - lxw_snprintf(data, LXW_UINT32_T_LENGTH, "%u", coords->col); _drawing_write_col(self, data); lxw_snprintf(data, LXW_UINT32_T_LENGTH, "%u", (uint32_t) coords->col_offset); @@ -188,42 +186,140 @@ _drawing_write_row(self, data); lxw_snprintf(data, LXW_UINT32_T_LENGTH, "%u", (uint32_t) coords->row_offset); _drawing_write_row_off(self, data); +} +/* + * Write the <xdr:from> element. + */ +STATIC void +_drawing_write_from(lxw_drawing *self, lxw_drawing_coords *coords) +{ + lxw_xml_start_tag(self->file, "xdr:from", NULL); + + _drawing_write_coords(self, coords); + lxw_xml_end_tag(self->file, "xdr:from"); } /* * Write the <xdr:to> element. */ STATIC void _drawing_write_to(lxw_drawing *self, lxw_drawing_coords *coords) { - char data[LXW_UINT32_T_LENGTH]; - lxw_xml_start_tag(self->file, "xdr:to", NULL); - lxw_snprintf(data, LXW_UINT32_T_LENGTH, "%u", coords->col); - _drawing_write_col(self, data); + _drawing_write_coords(self, coords); - lxw_snprintf(data, LXW_UINT32_T_LENGTH, "%u", - (uint32_t) coords->col_offset); - _drawing_write_col_off(self, data); + lxw_xml_end_tag(self->file, "xdr:to"); +} - lxw_snprintf(data, LXW_UINT32_T_LENGTH, "%u", coords->row); - _drawing_write_row(self, data); +/* + * Write the <a:hlinkClick> element. + */ +STATIC void +_drawing_write_a_hlink_click(lxw_drawing *self, uint32_t rel_index, char *tip) +{ + struct xml_attribute_list attributes; + struct xml_attribute *attribute; + char xmlns_r[] = "http://schemas.openxmlformats.org/" + "officeDocument/2006/relationships"; + char r_id[LXW_MAX_ATTRIBUTE_LENGTH]; - lxw_snprintf(data, LXW_UINT32_T_LENGTH, "%u", - (uint32_t) coords->row_offset); - _drawing_write_row_off(self, data); + lxw_snprintf(r_id, LXW_ATTR_32, "rId%d", rel_index); - lxw_xml_end_tag(self->file, "xdr:to"); + LXW_INIT_ATTRIBUTES(); + LXW_PUSH_ATTRIBUTES_STR("xmlns:r", xmlns_r); + LXW_PUSH_ATTRIBUTES_STR("r:id", r_id); + + if (tip) + LXW_PUSH_ATTRIBUTES_STR("tooltip", tip); + + lxw_xml_empty_tag(self->file, "a:hlinkClick", &attributes); + + LXW_FREE_ATTRIBUTES(); } /* + * Write the <a16:creationId> element. + */ +STATIC void +_drawing_write_a16_creation_id(lxw_drawing *self) +{ + struct xml_attribute_list attributes; + struct xml_attribute *attribute; + char xmlns[] = "http://schemas.microsoft.com/office/drawing/2014/main"; + + LXW_INIT_ATTRIBUTES(); + LXW_PUSH_ATTRIBUTES_STR("xmlns:a16", xmlns); + LXW_PUSH_ATTRIBUTES_STR("id", "{00000000-0008-0000-0000-000002000000}"); + + lxw_xml_empty_tag(self->file, "a16:creationId", &attributes); + + LXW_FREE_ATTRIBUTES(); +} + +/* + * Write the <adec:decorative> element. + */ +STATIC void +_workbook_write_adec_decorative(lxw_drawing *self) +{ + struct xml_attribute_list attributes; + struct xml_attribute *attribute; + char xmlns[] = + "http://schemas.microsoft.com/office/drawing/2017/decorative"; + + LXW_INIT_ATTRIBUTES(); + LXW_PUSH_ATTRIBUTES_STR("xmlns:adec", xmlns); + LXW_PUSH_ATTRIBUTES_STR("val", "1"); + + lxw_xml_empty_tag(self->file, "adec:decorative", &attributes); + + LXW_FREE_ATTRIBUTES(); +} + +/* + * Write the <a:ext> element. + */ +STATIC void +_drawing_write_uri_ext(lxw_drawing *self, char *uri) +{ + struct xml_attribute_list attributes; + struct xml_attribute *attribute; + + LXW_INIT_ATTRIBUTES(); + LXW_PUSH_ATTRIBUTES_STR("uri", uri); + + lxw_xml_start_tag(self->file, "a:ext", &attributes); + + LXW_FREE_ATTRIBUTES(); +} + +/* + * Write the decorative elements. + */ +STATIC void +_workbook_write_decorative(lxw_drawing *self) +{ + lxw_xml_start_tag(self->file, "a:extLst", NULL); + + _drawing_write_uri_ext(self, "{FF2B5EF4-FFF2-40B4-BE49-F238E27FC236}"); + _drawing_write_a16_creation_id(self); + lxw_xml_end_tag(self->file, "a:ext"); + + _drawing_write_uri_ext(self, "{C183D7F6-B498-43B3-948B-1728B52AA6E4}"); + _workbook_write_adec_decorative(self); + lxw_xml_end_tag(self->file, "a:ext"); + + lxw_xml_end_tag(self->file, "a:extLst"); +} + +/* * Write the <xdr:cNvPr> element. */ STATIC void _drawing_write_c_nv_pr(lxw_drawing *self, char *object_name, uint32_t index, lxw_drawing_object *drawing_object) @@ -237,15 +333,38 @@ LXW_INIT_ATTRIBUTES(); LXW_PUSH_ATTRIBUTES_INT("id", index + 1); LXW_PUSH_ATTRIBUTES_STR("name", name); - if (drawing_object && drawing_object->description) + if (drawing_object && drawing_object->description + && strlen(drawing_object->description) + && !drawing_object->decorative) { + LXW_PUSH_ATTRIBUTES_STR("descr", drawing_object->description); + } - lxw_xml_empty_tag(self->file, "xdr:cNvPr", &attributes); + if (drawing_object + && (drawing_object->url_rel_index || drawing_object->decorative)) { + lxw_xml_start_tag(self->file, "xdr:cNvPr", &attributes); + if (drawing_object->url_rel_index) { + /* Write the a:hlinkClick element. */ + _drawing_write_a_hlink_click(self, + drawing_object->url_rel_index, + drawing_object->tip); + } + + if (drawing_object->decorative) { + _workbook_write_decorative(self); + } + + lxw_xml_end_tag(self->file, "xdr:cNvPr"); + } + else { + lxw_xml_empty_tag(self->file, "xdr:cNvPr", &attributes); + } + LXW_FREE_ATTRIBUTES(); } /* * Write the <a:picLocks> element. @@ -470,11 +589,11 @@ /* Write the xdr:nvPicPr element. */ _drawing_write_nv_pic_pr(self, index, drawing_object); /* Write the xdr:blipFill element. */ - _drawing_write_blip_fill(self, index); + _drawing_write_blip_fill(self, drawing_object->rel_index); /* Write the xdr:spPr element. */ _drawing_write_sp_pr(self, drawing_object); lxw_xml_end_tag(self->file, "xdr:pic"); @@ -527,16 +646,17 @@ /* * Write the <xdr:nvGraphicFramePr> element. */ STATIC void -_drawing_write_nv_graphic_frame_pr(lxw_drawing *self, uint32_t index) +_drawing_write_nv_graphic_frame_pr(lxw_drawing *self, uint32_t index, + lxw_drawing_object *drawing_object) { lxw_xml_start_tag(self->file, "xdr:nvGraphicFramePr", NULL); /* Write the xdr:cNvPr element. */ - _drawing_write_c_nv_pr(self, "Chart", index, NULL); + _drawing_write_c_nv_pr(self, "Chart", index, drawing_object); /* Write the xdr:cNvGraphicFramePr element. */ _drawing_write_c_nv_graphic_frame_pr(self); lxw_xml_end_tag(self->file, "xdr:nvGraphicFramePr"); @@ -659,28 +779,30 @@ /* * Write the <xdr:graphicFrame> element. */ STATIC void -_drawing_write_graphic_frame(lxw_drawing *self, uint32_t index) +_drawing_write_graphic_frame(lxw_drawing *self, uint32_t index, + uint32_t rel_index, + lxw_drawing_object *drawing_object) { struct xml_attribute_list attributes; struct xml_attribute *attribute; LXW_INIT_ATTRIBUTES(); LXW_PUSH_ATTRIBUTES_STR("macro", ""); lxw_xml_start_tag(self->file, "xdr:graphicFrame", &attributes); /* Write the xdr:nvGraphicFramePr element. */ - _drawing_write_nv_graphic_frame_pr(self, index); + _drawing_write_nv_graphic_frame_pr(self, index, drawing_object); /* Write the xdr:xfrm element. */ _drawing_write_xfrm(self); /* Write the a:graphic element. */ - _drawing_write_a_graphic(self, index); + _drawing_write_a_graphic(self, rel_index); lxw_xml_end_tag(self->file, "xdr:graphicFrame"); LXW_FREE_ATTRIBUTES(); } @@ -695,28 +817,26 @@ struct xml_attribute_list attributes; struct xml_attribute *attribute; LXW_INIT_ATTRIBUTES(); - if (drawing_object->anchor_type == LXW_ANCHOR_TYPE_IMAGE) { + if (drawing_object->anchor == LXW_OBJECT_MOVE_DONT_SIZE) + LXW_PUSH_ATTRIBUTES_STR("editAs", "oneCell"); + else if (drawing_object->anchor == LXW_OBJECT_DONT_MOVE_DONT_SIZE) + LXW_PUSH_ATTRIBUTES_STR("editAs", "absolute"); - if (drawing_object->edit_as == LXW_ANCHOR_EDIT_AS_ABSOLUTE) - LXW_PUSH_ATTRIBUTES_STR("editAs", "absolute"); - else if (drawing_object->edit_as != LXW_ANCHOR_EDIT_AS_RELATIVE) - LXW_PUSH_ATTRIBUTES_STR("editAs", "oneCell"); - } - lxw_xml_start_tag(self->file, "xdr:twoCellAnchor", &attributes); _drawing_write_from(self, &drawing_object->from); _drawing_write_to(self, &drawing_object->to); - if (drawing_object->anchor_type == LXW_ANCHOR_TYPE_CHART) { + if (drawing_object->type == LXW_DRAWING_CHART) { /* Write the xdr:graphicFrame element for charts. */ - _drawing_write_graphic_frame(self, index); + _drawing_write_graphic_frame(self, index, drawing_object->rel_index, + drawing_object); } - else if (drawing_object->anchor_type == LXW_ANCHOR_TYPE_IMAGE) { + else if (drawing_object->type == LXW_DRAWING_IMAGE) { /* Write the xdr:pic element. */ _drawing_write_pic(self, index, drawing_object); } else { /* Write the xdr:sp element for shapes. */ @@ -770,11 +890,11 @@ /* * Write the <xdr:absoluteAnchor> element. */ STATIC void -_drawing_write_absolute_anchor(lxw_drawing *self) +_drawing_write_absolute_anchor(lxw_drawing *self, uint32_t frame_index) { lxw_xml_start_tag(self->file, "xdr:absoluteAnchor", NULL); if (self->orientation == LXW_LANDSCAPE) { /* Write the xdr:pos element. */ @@ -789,11 +909,11 @@ /* Write the xdr:ext element. */ _drawing_write_ext(self, 6162675, 6124575); } - _drawing_write_graphic_frame(self, 1); + _drawing_write_graphic_frame(self, frame_index, frame_index, NULL); /* Write the xdr:clientData element. */ _drawing_write_client_data(self); lxw_xml_end_tag(self->file, "xdr:absoluteAnchor"); @@ -828,10 +948,10 @@ index++; } } else { /* Write the xdr:absoluteAnchor element. Mainly for chartsheets. */ - _drawing_write_absolute_anchor(self); + _drawing_write_absolute_anchor(self, 1); } lxw_xml_end_tag(self->file, "xdr:wsDr"); }