mirror of
https://github.com/jmcnamara/libxlsxwriter.git
synced 2026-05-21 06:45:21 -06:00
First functional test of insert_image().
This commit is contained in:
parent
79505061eb
commit
03e5deaa8f
18 changed files with 306 additions and 33 deletions
1
.indent.pro
vendored
1
.indent.pro
vendored
|
|
@ -65,7 +65,6 @@
|
||||||
-T lxw_hash_table
|
-T lxw_hash_table
|
||||||
-T lxw_header_footer_options
|
-T lxw_header_footer_options
|
||||||
-T lxw_heading_pair
|
-T lxw_heading_pair
|
||||||
-T lxw_image_meta
|
|
||||||
-T lxw_image_options
|
-T lxw_image_options
|
||||||
-T lxw_merged_range
|
-T lxw_merged_range
|
||||||
-T lxw_packager
|
-T lxw_packager
|
||||||
|
|
|
||||||
|
|
@ -28,6 +28,7 @@ enum lxw_boolean {
|
||||||
#define LXW_SHEETNAME_LEN 65
|
#define LXW_SHEETNAME_LEN 65
|
||||||
#define LXW_UINT32_T_LEN 11 /* Length of 4294967296\0. */
|
#define LXW_UINT32_T_LEN 11 /* Length of 4294967296\0. */
|
||||||
#define LXW_IGNORE 1
|
#define LXW_IGNORE 1
|
||||||
|
#define FILENAME_LEN 128
|
||||||
|
|
||||||
#define LXW_ERROR(message) \
|
#define LXW_ERROR(message) \
|
||||||
fprintf(stderr, "[ERROR][%s:%d]: " message "\n", __FILE__, __LINE__)
|
fprintf(stderr, "[ERROR][%s:%d]: " message "\n", __FILE__, __LINE__)
|
||||||
|
|
|
||||||
|
|
@ -45,7 +45,8 @@ void _ct_add_default(lxw_content_types *self, const char *key,
|
||||||
const char *value);
|
const char *value);
|
||||||
void _ct_add_override(lxw_content_types *self, const char *key,
|
void _ct_add_override(lxw_content_types *self, const char *key,
|
||||||
const char *value);
|
const char *value);
|
||||||
void _ct_add_worksheet_name(lxw_content_types *self, const char *str);
|
void _ct_add_worksheet_name(lxw_content_types *self, const char *name);
|
||||||
|
void _ct_add_drawing_name(lxw_content_types *self, const char *name);
|
||||||
void _ct_add_shared_strings(lxw_content_types *self);
|
void _ct_add_shared_strings(lxw_content_types *self);
|
||||||
void _ct_add_calc_chain(lxw_content_types *self);
|
void _ct_add_calc_chain(lxw_content_types *self);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -86,6 +86,8 @@ lxw_drawing *_new_drawing();
|
||||||
void _free_drawing(lxw_drawing *drawing);
|
void _free_drawing(lxw_drawing *drawing);
|
||||||
void _drawing_assemble_xml_file(lxw_drawing *self);
|
void _drawing_assemble_xml_file(lxw_drawing *self);
|
||||||
void _free_drawing_object(struct lxw_drawing_object *drawing_object);
|
void _free_drawing_object(struct lxw_drawing_object *drawing_object);
|
||||||
|
void _add_drawing_object(lxw_drawing *drawing,
|
||||||
|
lxw_drawing_object *drawing_object);
|
||||||
|
|
||||||
/* Declarations required for unit testing. */
|
/* Declarations required for unit testing. */
|
||||||
#ifdef TESTING
|
#ifdef TESTING
|
||||||
|
|
|
||||||
|
|
@ -24,7 +24,6 @@
|
||||||
#include "content_types.h"
|
#include "content_types.h"
|
||||||
#include "relationships.h"
|
#include "relationships.h"
|
||||||
|
|
||||||
#define FILENAME_LEN 128
|
|
||||||
#define LXW_ZIP_BUFFER_SIZE (16384)
|
#define LXW_ZIP_BUFFER_SIZE (16384)
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
@ -41,6 +40,8 @@ typedef struct lxw_packager {
|
||||||
char *filename;
|
char *filename;
|
||||||
char *buffer;
|
char *buffer;
|
||||||
|
|
||||||
|
uint16_t drawing_count;
|
||||||
|
|
||||||
} lxw_packager;
|
} lxw_packager;
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -200,6 +200,10 @@ typedef struct lxw_workbook {
|
||||||
uint16_t fill_count;
|
uint16_t fill_count;
|
||||||
uint8_t optimize;
|
uint8_t optimize;
|
||||||
|
|
||||||
|
uint8_t has_png;
|
||||||
|
uint8_t has_jpg;
|
||||||
|
uint8_t has_bmp;
|
||||||
|
|
||||||
lxw_hash_table *used_xf_formats;
|
lxw_hash_table *used_xf_formats;
|
||||||
|
|
||||||
} lxw_workbook;
|
} lxw_workbook;
|
||||||
|
|
|
||||||
|
|
@ -49,6 +49,7 @@
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
#include "shared_strings.h"
|
#include "shared_strings.h"
|
||||||
|
#include "drawing.h"
|
||||||
#include "common.h"
|
#include "common.h"
|
||||||
#include "format.h"
|
#include "format.h"
|
||||||
#include "utility.h"
|
#include "utility.h"
|
||||||
|
|
@ -465,11 +466,15 @@ typedef struct lxw_worksheet {
|
||||||
lxw_col_t *vbreaks;
|
lxw_col_t *vbreaks;
|
||||||
|
|
||||||
struct lxw_rel_tuples *external_hyperlinks;
|
struct lxw_rel_tuples *external_hyperlinks;
|
||||||
|
struct lxw_rel_tuples *external_drawing_links;
|
||||||
|
struct lxw_rel_tuples *drawing_links;
|
||||||
|
|
||||||
struct lxw_panes panes;
|
struct lxw_panes panes;
|
||||||
|
|
||||||
struct lxw_protection protection;
|
struct lxw_protection protection;
|
||||||
|
|
||||||
|
lxw_drawing *drawing;
|
||||||
|
|
||||||
STAILQ_ENTRY (lxw_worksheet) list_pointers;
|
STAILQ_ENTRY (lxw_worksheet) list_pointers;
|
||||||
|
|
||||||
} lxw_worksheet;
|
} lxw_worksheet;
|
||||||
|
|
|
||||||
|
|
@ -284,15 +284,21 @@ mem_error:
|
||||||
* Add the name of a worksheet to the ContentTypes overrides.
|
* Add the name of a worksheet to the ContentTypes overrides.
|
||||||
*/
|
*/
|
||||||
void
|
void
|
||||||
_ct_add_worksheet_name(lxw_content_types *self, const char *str)
|
_ct_add_worksheet_name(lxw_content_types *self, const char *name)
|
||||||
{
|
{
|
||||||
char name[MAX_ATTRIBUTE_LENGTH];
|
|
||||||
lxw_snprintf(name, MAX_ATTRIBUTE_LENGTH, "/xl/worksheets/%s.xml", str);
|
|
||||||
|
|
||||||
_ct_add_override(self, name,
|
_ct_add_override(self, name,
|
||||||
LXW_APP_DOCUMENT "spreadsheetml.worksheet+xml");
|
LXW_APP_DOCUMENT "spreadsheetml.worksheet+xml");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Add the name of a drawing to the ContentTypes overrides.
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
_ct_add_drawing_name(lxw_content_types *self, const char *name)
|
||||||
|
{
|
||||||
|
_ct_add_override(self, name, LXW_APP_DOCUMENT "drawing+xml");
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Add the sharedStrings link to the ContentTypes overrides.
|
* Add the sharedStrings link to the ContentTypes overrides.
|
||||||
*/
|
*/
|
||||||
|
|
|
||||||
|
|
@ -86,6 +86,16 @@ _free_drawing(lxw_drawing *drawing)
|
||||||
free(drawing);
|
free(drawing);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Add a drawing object to the drawing collection.
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
_add_drawing_object(lxw_drawing *drawing, lxw_drawing_object *drawing_object)
|
||||||
|
{
|
||||||
|
STAILQ_INSERT_TAIL(drawing->drawing_objects, drawing_object,
|
||||||
|
list_pointers);
|
||||||
|
}
|
||||||
|
|
||||||
/*****************************************************************************
|
/*****************************************************************************
|
||||||
*
|
*
|
||||||
* XML functions.
|
* XML functions.
|
||||||
|
|
|
||||||
141
src/packager.c
141
src/packager.c
|
|
@ -169,6 +169,71 @@ _write_worksheet_files(lxw_packager *self)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Write the /xl/media/image?.xml files.
|
||||||
|
*/
|
||||||
|
STATIC uint8_t
|
||||||
|
_write_image_files(lxw_packager *self)
|
||||||
|
{
|
||||||
|
lxw_workbook *workbook = self->workbook;
|
||||||
|
lxw_worksheet *worksheet;
|
||||||
|
lxw_image_options *image;
|
||||||
|
|
||||||
|
char filename[FILENAME_LEN] = { 0 };
|
||||||
|
uint16_t index = 1;
|
||||||
|
|
||||||
|
STAILQ_FOREACH(worksheet, workbook->worksheets, list_pointers) {
|
||||||
|
|
||||||
|
if (STAILQ_EMPTY(worksheet->images))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
STAILQ_FOREACH(image, worksheet->images, list_pointers) {
|
||||||
|
|
||||||
|
lxw_snprintf(filename, FILENAME_LEN,
|
||||||
|
"xl/media/image%d.png", index++);
|
||||||
|
|
||||||
|
rewind(image->stream);
|
||||||
|
|
||||||
|
_add_file_to_zip(self, image->stream, filename);
|
||||||
|
|
||||||
|
fclose(image->stream);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Write the drawing files.
|
||||||
|
*/
|
||||||
|
STATIC uint8_t
|
||||||
|
_write_drawing_files(lxw_packager *self)
|
||||||
|
{
|
||||||
|
lxw_workbook *workbook = self->workbook;
|
||||||
|
lxw_worksheet *worksheet;
|
||||||
|
lxw_drawing *drawing;
|
||||||
|
char filename[FILENAME_LEN] = { 0 };
|
||||||
|
uint16_t index = 1;
|
||||||
|
|
||||||
|
STAILQ_FOREACH(worksheet, workbook->worksheets, list_pointers) {
|
||||||
|
drawing = worksheet->drawing;
|
||||||
|
|
||||||
|
if (drawing) {
|
||||||
|
lxw_snprintf(filename, FILENAME_LEN,
|
||||||
|
"xl/drawings/drawing%d.xml", index++);
|
||||||
|
|
||||||
|
drawing->file = lxw_tmpfile();
|
||||||
|
_drawing_assemble_xml_file(drawing);
|
||||||
|
_add_file_to_zip(self, drawing->file, filename);
|
||||||
|
fclose(drawing->file);
|
||||||
|
|
||||||
|
self->drawing_count++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Write the sharedStrings.xml file.
|
* Write the sharedStrings.xml file.
|
||||||
*/
|
*/
|
||||||
|
|
@ -340,14 +405,24 @@ _write_content_types_file(lxw_packager *self)
|
||||||
lxw_content_types *content_types = _new_content_types();
|
lxw_content_types *content_types = _new_content_types();
|
||||||
lxw_workbook *workbook = self->workbook;
|
lxw_workbook *workbook = self->workbook;
|
||||||
lxw_worksheet *worksheet;
|
lxw_worksheet *worksheet;
|
||||||
char sheetname[FILENAME_LEN] = { 0 };
|
char filename[MAX_ATTRIBUTE_LENGTH] = { 0 };
|
||||||
uint16_t index = 1;
|
uint16_t index = 1;
|
||||||
|
|
||||||
content_types->file = lxw_tmpfile();
|
content_types->file = lxw_tmpfile();
|
||||||
|
|
||||||
|
if (workbook->has_png)
|
||||||
|
_ct_add_default(content_types, "png", "image/png");
|
||||||
|
|
||||||
STAILQ_FOREACH(worksheet, workbook->worksheets, list_pointers) {
|
STAILQ_FOREACH(worksheet, workbook->worksheets, list_pointers) {
|
||||||
lxw_snprintf(sheetname, FILENAME_LEN, "sheet%d", index++);
|
lxw_snprintf(filename, FILENAME_LEN,
|
||||||
_ct_add_worksheet_name(content_types, sheetname);
|
"/xl/worksheets/sheet%d.xml", index++);
|
||||||
|
_ct_add_worksheet_name(content_types, filename);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (index = 1; index <= self->drawing_count; index++) {
|
||||||
|
lxw_snprintf(filename, FILENAME_LEN,
|
||||||
|
"/xl/drawings/drawing%d.xml", index++);
|
||||||
|
_ct_add_drawing_name(content_types, filename);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (workbook->sst->string_count)
|
if (workbook->sst->string_count)
|
||||||
|
|
@ -409,7 +484,7 @@ STATIC uint8_t
|
||||||
_write_worksheet_rels_file(lxw_packager *self)
|
_write_worksheet_rels_file(lxw_packager *self)
|
||||||
{
|
{
|
||||||
lxw_relationships *rels;
|
lxw_relationships *rels;
|
||||||
lxw_rel_tuple *hlink;
|
lxw_rel_tuple *rel;
|
||||||
lxw_workbook *workbook = self->workbook;
|
lxw_workbook *workbook = self->workbook;
|
||||||
lxw_worksheet *worksheet;
|
lxw_worksheet *worksheet;
|
||||||
char sheetname[FILENAME_LEN] = { 0 };
|
char sheetname[FILENAME_LEN] = { 0 };
|
||||||
|
|
@ -417,16 +492,21 @@ _write_worksheet_rels_file(lxw_packager *self)
|
||||||
|
|
||||||
STAILQ_FOREACH(worksheet, workbook->worksheets, list_pointers) {
|
STAILQ_FOREACH(worksheet, workbook->worksheets, list_pointers) {
|
||||||
|
|
||||||
if (STAILQ_EMPTY(worksheet->external_hyperlinks))
|
if (STAILQ_EMPTY(worksheet->external_hyperlinks) &&
|
||||||
|
STAILQ_EMPTY(worksheet->external_drawing_links))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
rels = _new_relationships();
|
rels = _new_relationships();
|
||||||
rels->file = lxw_tmpfile();
|
rels->file = lxw_tmpfile();
|
||||||
|
|
||||||
STAILQ_FOREACH(hlink, worksheet->external_hyperlinks, list_pointers) {
|
STAILQ_FOREACH(rel, worksheet->external_hyperlinks, list_pointers) {
|
||||||
_add_worksheet_relationship(rels, hlink->type, hlink->target,
|
_add_worksheet_relationship(rels, rel->type, rel->target,
|
||||||
hlink->target_mode);
|
rel->target_mode);
|
||||||
|
}
|
||||||
|
|
||||||
|
STAILQ_FOREACH(rel, worksheet->external_drawing_links, list_pointers) {
|
||||||
|
_add_worksheet_relationship(rels, rel->type, rel->target,
|
||||||
|
rel->target_mode);
|
||||||
}
|
}
|
||||||
|
|
||||||
lxw_snprintf(sheetname, FILENAME_LEN,
|
lxw_snprintf(sheetname, FILENAME_LEN,
|
||||||
|
|
@ -443,6 +523,48 @@ _write_worksheet_rels_file(lxw_packager *self)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Write the drawing .rels files for worksheets that contain charts or
|
||||||
|
* drawings.
|
||||||
|
*/
|
||||||
|
STATIC uint8_t
|
||||||
|
_write_drawing_rels_file(lxw_packager *self)
|
||||||
|
{
|
||||||
|
lxw_relationships *rels;
|
||||||
|
lxw_rel_tuple *rel;
|
||||||
|
lxw_workbook *workbook = self->workbook;
|
||||||
|
lxw_worksheet *worksheet;
|
||||||
|
char sheetname[FILENAME_LEN] = { 0 };
|
||||||
|
uint16_t index = 1;
|
||||||
|
|
||||||
|
STAILQ_FOREACH(worksheet, workbook->worksheets, list_pointers) {
|
||||||
|
|
||||||
|
if (STAILQ_EMPTY(worksheet->drawing_links))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
rels = _new_relationships();
|
||||||
|
rels->file = lxw_tmpfile();
|
||||||
|
|
||||||
|
STAILQ_FOREACH(rel, worksheet->drawing_links, list_pointers) {
|
||||||
|
_add_worksheet_relationship(rels, rel->type, rel->target,
|
||||||
|
rel->target_mode);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
lxw_snprintf(sheetname, FILENAME_LEN,
|
||||||
|
"xl/drawings/_rels/drawing%d.xml.rels", index++);
|
||||||
|
|
||||||
|
_relationships_assemble_xml_file(rels);
|
||||||
|
|
||||||
|
_add_file_to_zip(self, rels->file, sheetname);
|
||||||
|
|
||||||
|
fclose(rels->file);
|
||||||
|
_free_relationships(rels);
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Write the _rels/.rels xml file.
|
* Write the _rels/.rels xml file.
|
||||||
*/
|
*/
|
||||||
|
|
@ -543,6 +665,7 @@ _create_package(lxw_packager *self)
|
||||||
|
|
||||||
_write_worksheet_files(self);
|
_write_worksheet_files(self);
|
||||||
_write_workbook_file(self);
|
_write_workbook_file(self);
|
||||||
|
_write_drawing_files(self);
|
||||||
_write_shared_strings_file(self);
|
_write_shared_strings_file(self);
|
||||||
_write_app_file(self);
|
_write_app_file(self);
|
||||||
_write_core_file(self);
|
_write_core_file(self);
|
||||||
|
|
@ -551,6 +674,8 @@ _create_package(lxw_packager *self)
|
||||||
_write_content_types_file(self);
|
_write_content_types_file(self);
|
||||||
_write_workbook_rels_file(self);
|
_write_workbook_rels_file(self);
|
||||||
_write_worksheet_rels_file(self);
|
_write_worksheet_rels_file(self);
|
||||||
|
_write_drawing_rels_file(self);
|
||||||
|
_write_image_files(self);
|
||||||
_write_root_rels_file(self);
|
_write_root_rels_file(self);
|
||||||
|
|
||||||
zipClose(self->zipfile, NULL);
|
zipClose(self->zipfile, NULL);
|
||||||
|
|
|
||||||
|
|
@ -691,11 +691,13 @@ _prepare_drawings(lxw_workbook *self)
|
||||||
if (_get_image_properties(image_options) != 0)
|
if (_get_image_properties(image_options) != 0)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
if (image_options->image_type == IMAGE_PNG)
|
||||||
|
self->has_png = LXW_TRUE;
|
||||||
|
|
||||||
image_ref_id++;
|
image_ref_id++;
|
||||||
|
|
||||||
/*sheet->_prepare_image(index, image_ref_id, drawing_id, width,
|
_worksheet_prepare_image(worksheet, image_ref_id, drawing_id,
|
||||||
height, name, type);
|
image_options);
|
||||||
*/
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
103
src/worksheet.c
103
src/worksheet.c
|
|
@ -12,7 +12,6 @@
|
||||||
#include "xlsxwriter/xmlwriter.h"
|
#include "xlsxwriter/xmlwriter.h"
|
||||||
#include "xlsxwriter/worksheet.h"
|
#include "xlsxwriter/worksheet.h"
|
||||||
#include "xlsxwriter/format.h"
|
#include "xlsxwriter/format.h"
|
||||||
#include "xlsxwriter/drawing.h"
|
|
||||||
#include "xlsxwriter/utility.h"
|
#include "xlsxwriter/utility.h"
|
||||||
#include "xlsxwriter/relationships.h"
|
#include "xlsxwriter/relationships.h"
|
||||||
|
|
||||||
|
|
@ -86,12 +85,21 @@ _new_worksheet(lxw_worksheet_init_data *init_data)
|
||||||
worksheet->external_hyperlinks = calloc(1, sizeof(struct lxw_rel_tuples));
|
worksheet->external_hyperlinks = calloc(1, sizeof(struct lxw_rel_tuples));
|
||||||
GOTO_LABEL_ON_MEM_ERROR(worksheet->external_hyperlinks, mem_error);
|
GOTO_LABEL_ON_MEM_ERROR(worksheet->external_hyperlinks, mem_error);
|
||||||
|
|
||||||
|
worksheet->external_drawing_links =
|
||||||
|
calloc(1, sizeof(struct lxw_rel_tuples));
|
||||||
|
GOTO_LABEL_ON_MEM_ERROR(worksheet->external_drawing_links, mem_error);
|
||||||
|
|
||||||
|
worksheet->drawing_links = calloc(1, sizeof(struct lxw_rel_tuples));
|
||||||
|
GOTO_LABEL_ON_MEM_ERROR(worksheet->drawing_links, mem_error);
|
||||||
|
|
||||||
RB_INIT(worksheet->table);
|
RB_INIT(worksheet->table);
|
||||||
RB_INIT(worksheet->hyperlinks);
|
RB_INIT(worksheet->hyperlinks);
|
||||||
STAILQ_INIT(worksheet->merged_ranges);
|
STAILQ_INIT(worksheet->merged_ranges);
|
||||||
STAILQ_INIT(worksheet->images);
|
STAILQ_INIT(worksheet->images);
|
||||||
STAILQ_INIT(worksheet->selections);
|
STAILQ_INIT(worksheet->selections);
|
||||||
STAILQ_INIT(worksheet->external_hyperlinks);
|
STAILQ_INIT(worksheet->external_hyperlinks);
|
||||||
|
STAILQ_INIT(worksheet->external_drawing_links);
|
||||||
|
STAILQ_INIT(worksheet->drawing_links);
|
||||||
|
|
||||||
if (init_data && init_data->optimize) {
|
if (init_data && init_data->optimize) {
|
||||||
worksheet->optimize_tmpfile = lxw_tmpfile();
|
worksheet->optimize_tmpfile = lxw_tmpfile();
|
||||||
|
|
@ -225,7 +233,7 @@ _free_worksheet(lxw_worksheet *worksheet)
|
||||||
lxw_merged_range *merged_range;
|
lxw_merged_range *merged_range;
|
||||||
lxw_image_options *image;
|
lxw_image_options *image;
|
||||||
lxw_selection *selection;
|
lxw_selection *selection;
|
||||||
lxw_rel_tuple *external_hyperlink;
|
lxw_rel_tuple *relationship;
|
||||||
|
|
||||||
if (!worksheet)
|
if (!worksheet)
|
||||||
return;
|
return;
|
||||||
|
|
@ -295,17 +303,37 @@ _free_worksheet(lxw_worksheet *worksheet)
|
||||||
free(worksheet->selections);
|
free(worksheet->selections);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* TODO. Add function for freeing the relationship lists. */
|
||||||
while (!STAILQ_EMPTY(worksheet->external_hyperlinks)) {
|
while (!STAILQ_EMPTY(worksheet->external_hyperlinks)) {
|
||||||
external_hyperlink = STAILQ_FIRST(worksheet->external_hyperlinks);
|
relationship = STAILQ_FIRST(worksheet->external_hyperlinks);
|
||||||
STAILQ_REMOVE_HEAD(worksheet->external_hyperlinks, list_pointers);
|
STAILQ_REMOVE_HEAD(worksheet->external_hyperlinks, list_pointers);
|
||||||
free(external_hyperlink->type);
|
free(relationship->type);
|
||||||
free(external_hyperlink->target);
|
free(relationship->target);
|
||||||
free(external_hyperlink->target_mode);
|
free(relationship->target_mode);
|
||||||
free(external_hyperlink);
|
free(relationship);
|
||||||
}
|
}
|
||||||
|
|
||||||
free(worksheet->external_hyperlinks);
|
free(worksheet->external_hyperlinks);
|
||||||
|
|
||||||
|
while (!STAILQ_EMPTY(worksheet->external_drawing_links)) {
|
||||||
|
relationship = STAILQ_FIRST(worksheet->external_drawing_links);
|
||||||
|
STAILQ_REMOVE_HEAD(worksheet->external_drawing_links, list_pointers);
|
||||||
|
free(relationship->type);
|
||||||
|
free(relationship->target);
|
||||||
|
free(relationship->target_mode);
|
||||||
|
free(relationship);
|
||||||
|
}
|
||||||
|
free(worksheet->external_drawing_links);
|
||||||
|
|
||||||
|
while (!STAILQ_EMPTY(worksheet->drawing_links)) {
|
||||||
|
relationship = STAILQ_FIRST(worksheet->drawing_links);
|
||||||
|
STAILQ_REMOVE_HEAD(worksheet->drawing_links, list_pointers);
|
||||||
|
free(relationship->type);
|
||||||
|
free(relationship->target);
|
||||||
|
free(relationship->target_mode);
|
||||||
|
free(relationship);
|
||||||
|
}
|
||||||
|
free(worksheet->drawing_links);
|
||||||
|
|
||||||
if (worksheet->array) {
|
if (worksheet->array) {
|
||||||
for (col = 0; col < LXW_COL_MAX; col++) {
|
for (col = 0; col < LXW_COL_MAX; col++) {
|
||||||
_free_cell(worksheet->array[col]);
|
_free_cell(worksheet->array[col]);
|
||||||
|
|
@ -316,6 +344,9 @@ _free_worksheet(lxw_worksheet *worksheet)
|
||||||
if (worksheet->optimize_row)
|
if (worksheet->optimize_row)
|
||||||
free(worksheet->optimize_row);
|
free(worksheet->optimize_row);
|
||||||
|
|
||||||
|
if (worksheet->drawing)
|
||||||
|
_free_drawing(worksheet->drawing);
|
||||||
|
|
||||||
free(worksheet->name);
|
free(worksheet->name);
|
||||||
free(worksheet->quoted_name);
|
free(worksheet->quoted_name);
|
||||||
|
|
||||||
|
|
@ -1700,12 +1731,39 @@ _worksheet_prepare_image(lxw_worksheet *self,
|
||||||
lxw_image_options *image)
|
lxw_image_options *image)
|
||||||
{
|
{
|
||||||
lxw_drawing_object *drawing_object;
|
lxw_drawing_object *drawing_object;
|
||||||
|
lxw_rel_tuple *relationship;
|
||||||
double width;
|
double width;
|
||||||
double height;
|
double height;
|
||||||
|
char filename[FILENAME_LEN];
|
||||||
|
|
||||||
|
if (!self->drawing) {
|
||||||
|
self->drawing = _new_drawing();
|
||||||
|
self->drawing->embedded = LXW_TRUE;
|
||||||
|
RETURN_VOID_ON_MEM_ERROR(self->drawing);
|
||||||
|
|
||||||
|
relationship = calloc(1, sizeof(lxw_rel_tuple));
|
||||||
|
GOTO_LABEL_ON_MEM_ERROR(relationship, mem_error);
|
||||||
|
|
||||||
|
relationship->type = lxw_strdup("/drawing");
|
||||||
|
GOTO_LABEL_ON_MEM_ERROR(relationship->type, mem_error);
|
||||||
|
|
||||||
|
lxw_snprintf(filename, FILENAME_LEN, "../drawings/drawing%d.xml",
|
||||||
|
drawing_id);
|
||||||
|
|
||||||
|
relationship->target = lxw_strdup(filename);
|
||||||
|
GOTO_LABEL_ON_MEM_ERROR(relationship->target, mem_error);
|
||||||
|
|
||||||
|
STAILQ_INSERT_TAIL(self->external_drawing_links, relationship,
|
||||||
|
list_pointers);
|
||||||
|
}
|
||||||
|
|
||||||
drawing_object = calloc(1, sizeof(lxw_drawing_object));
|
drawing_object = calloc(1, sizeof(lxw_drawing_object));
|
||||||
RETURN_VOID_ON_MEM_ERROR(drawing_object);
|
RETURN_VOID_ON_MEM_ERROR(drawing_object);
|
||||||
|
|
||||||
|
drawing_object->anchor_type = LXW_ANCHOR_TYPE_IMAGE;
|
||||||
|
drawing_object->edit_as = LXW_ANCHOR_EDIT_AS_ONE_CELL;
|
||||||
|
drawing_object->description = lxw_strdup(image->short_name);
|
||||||
|
|
||||||
/* Scale to user scale. */
|
/* Scale to user scale. */
|
||||||
width = image->width * image->x_scale;
|
width = image->width * image->x_scale;
|
||||||
height = image->height * image->y_scale;
|
height = image->height * image->y_scale;
|
||||||
|
|
@ -1721,12 +1779,33 @@ _worksheet_prepare_image(lxw_worksheet *self,
|
||||||
_worksheet_position_object_emus(self, image, drawing_object);
|
_worksheet_position_object_emus(self, image, drawing_object);
|
||||||
|
|
||||||
/* Convert from pixels to emus. */
|
/* Convert from pixels to emus. */
|
||||||
image->width *= 9525;
|
drawing_object->width = image->width * 9525;
|
||||||
image->height *= 9525;
|
drawing_object->height = image->height * 9525;
|
||||||
|
|
||||||
image_ref_id++;
|
_add_drawing_object(self->drawing, drawing_object);
|
||||||
drawing_id++;
|
|
||||||
|
|
||||||
|
relationship = calloc(1, sizeof(lxw_rel_tuple));
|
||||||
|
GOTO_LABEL_ON_MEM_ERROR(relationship, mem_error);
|
||||||
|
|
||||||
|
relationship->type = lxw_strdup("/image");
|
||||||
|
GOTO_LABEL_ON_MEM_ERROR(relationship->type, mem_error);
|
||||||
|
|
||||||
|
lxw_snprintf(filename, 32, "../media/image%d.png", image_ref_id);
|
||||||
|
|
||||||
|
relationship->target = lxw_strdup(filename);
|
||||||
|
GOTO_LABEL_ON_MEM_ERROR(relationship->target, mem_error);
|
||||||
|
|
||||||
|
STAILQ_INSERT_TAIL(self->drawing_links, relationship, list_pointers);
|
||||||
|
|
||||||
|
return;
|
||||||
|
|
||||||
|
mem_error:
|
||||||
|
if (relationship) {
|
||||||
|
free(relationship->type);
|
||||||
|
free(relationship->target);
|
||||||
|
free(relationship->target_mode);
|
||||||
|
free(relationship);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*****************************************************************************
|
/*****************************************************************************
|
||||||
|
|
|
||||||
BIN
test/functional/src/images/red.png
Normal file
BIN
test/functional/src/images/red.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 200 B |
20
test/functional/src/test_image01.c
Normal file
20
test/functional/src/test_image01.c
Normal file
|
|
@ -0,0 +1,20 @@
|
||||||
|
/*****************************************************************************
|
||||||
|
* Test cases for libxlsxwriter.
|
||||||
|
*
|
||||||
|
* Test to compare output against Excel files.
|
||||||
|
*
|
||||||
|
* Copyright 2014-2015, John McNamara, jmcnamara@cpan.org
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "xlsxwriter.h"
|
||||||
|
|
||||||
|
int main() {
|
||||||
|
|
||||||
|
lxw_workbook *workbook = new_workbook("test_image01.xlsx");
|
||||||
|
lxw_worksheet *worksheet = workbook_add_worksheet(workbook, NULL);
|
||||||
|
|
||||||
|
worksheet_insert_image(worksheet, CELL("E9"), "images/red.png");
|
||||||
|
|
||||||
|
return workbook_close(workbook);
|
||||||
|
}
|
||||||
18
test/functional/test_image.py
Normal file
18
test/functional/test_image.py
Normal file
|
|
@ -0,0 +1,18 @@
|
||||||
|
###############################################################################
|
||||||
|
#
|
||||||
|
# Tests for libxlsxwriter.
|
||||||
|
#
|
||||||
|
# Copyright 2014-2015, John McNamara, jmcnamara@cpan.org
|
||||||
|
#
|
||||||
|
|
||||||
|
import base_test_class
|
||||||
|
|
||||||
|
class TestCompareXLSXFiles(base_test_class.XLSXBaseTest):
|
||||||
|
"""
|
||||||
|
Test file created with libxlsxwriter against a file created by Excel.
|
||||||
|
|
||||||
|
"""
|
||||||
|
|
||||||
|
def test_image01(self):
|
||||||
|
self.run_exe_test('test_image01')
|
||||||
|
|
||||||
BIN
test/functional/xlsx_files/image01.xlsx
Normal file
BIN
test/functional/xlsx_files/image01.xlsx
Normal file
Binary file not shown.
|
|
@ -37,7 +37,7 @@ CTEST(content_types, content_types01) {
|
||||||
lxw_content_types *content_types = _new_content_types();
|
lxw_content_types *content_types = _new_content_types();
|
||||||
content_types->file = testfile;
|
content_types->file = testfile;
|
||||||
|
|
||||||
_ct_add_worksheet_name(content_types, "sheet1");
|
_ct_add_worksheet_name(content_types, "/xl/worksheets/sheet1.xml");
|
||||||
_ct_add_default(content_types, "jpeg", "image/jpeg");
|
_ct_add_default(content_types, "jpeg", "image/jpeg");
|
||||||
_ct_add_shared_strings(content_types);
|
_ct_add_shared_strings(content_types);
|
||||||
_ct_add_calc_chain(content_types);
|
_ct_add_calc_chain(content_types);
|
||||||
|
|
|
||||||
|
|
@ -5,7 +5,7 @@
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <string.h>;
|
#include <string.h>
|
||||||
#include "../ctest.h"
|
#include "../ctest.h"
|
||||||
#include "../helper.h"
|
#include "../helper.h"
|
||||||
|
|
||||||
|
|
@ -88,7 +88,7 @@ CTEST(drawing, drawing_image01) {
|
||||||
drawing_object->width = 1142857;
|
drawing_object->width = 1142857;
|
||||||
drawing_object->height = 1142857;
|
drawing_object->height = 1142857;
|
||||||
|
|
||||||
STAILQ_INSERT_TAIL(drawing->drawing_objects, drawing_object, list_pointers);
|
_add_drawing_object(drawing, drawing_object);
|
||||||
|
|
||||||
_drawing_assemble_xml_file(drawing);
|
_drawing_assemble_xml_file(drawing);
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue