better data struct for embedded image

This commit is contained in:
Stefan Frederik 2022-01-19 23:28:19 +01:00
parent c8038ffdb8
commit c3af523559
11 changed files with 140 additions and 101 deletions

View File

@ -570,6 +570,49 @@ void remove_symbols(void)
dbg(1, "remove_symbols(): done\n");
}
/* what:
* 2: copy: drptr->extraptr <- srptr->extraptr
* 1: create
* 0: clear
*/
int setup_rect_extraptr(int what, xRect *drptr, xRect *srptr)
{
if(what==2) { /* copy */
if(drptr->flags & 1024) { /* embedded image */
xEmb_image *d, *s;
s = srptr->extraptr;
if(s) {
d = my_malloc(1478, sizeof(xEmb_image));
d->data = my_malloc(1479, s->data_size);
memcpy(d->data, s->data, s->data_size);
d->data_size = s->data_size;
drptr->extraptr = d;
} else {
drptr->extraptr = NULL;
}
}
} else if(what==1) { /* create */
if(drptr->flags & 1024) { /* embedded image */
if(!drptr->extraptr) {
xEmb_image *d;
d = my_malloc(1465, sizeof(xEmb_image));
d->data = NULL;
d->data_size = 0;
drptr->extraptr = d;
}
}
} else { /* clear */
if(drptr->flags & 1024) { /* embedded image */
if(drptr->extraptr) {
xEmb_image *d = drptr->extraptr;
if(d->data) my_free(1475, &d->data);
my_free(1476, &drptr->extraptr);
}
}
}
return 0;
}
void clear_drawing(void)
{
int i,j;
@ -612,10 +655,7 @@ void clear_drawing(void)
for(j=0;j<xctx->rects[i];j++)
{
my_free(700, &xctx->rect[i][j].prop_ptr);
if(xctx->rect[i][j].data) {
my_free(1467, &xctx->rect[i][j].data);
xctx->rect[i][j].data_size = 0;
}
setup_rect_extraptr(0, &xctx->rect[i][j], NULL);
}
for(j=0;j<xctx->arcs[i];j++)
{

View File

@ -2589,7 +2589,6 @@ static cairo_status_t png_writer(void *in_closure, const unsigned char *in_data,
return CAIRO_STATUS_SUCCESS;
}
int draw_images_all(void)
{
#if HAS_CAIRO==1
@ -2598,15 +2597,6 @@ int draw_images_all(void)
int save_bbx1, save_bby1, save_bbx2, save_bby2;
cairo_surface_t *image;
if(xctx->sem) {
bbox_set = 1;
save_bbx1 = xctx->bbx1;
save_bby1 = xctx->bby1;
save_bbx2 = xctx->bbx2;
save_bby2 = xctx->bby2;
bbox(END, 0.0, 0.0, 0.0, 0.0);
}
if(xctx->draw_single_layer==-1 || GRIDLAYER == xctx->draw_single_layer) {
if(xctx->enable_layer[GRIDLAYER]) for(i = 0; i < xctx->rects[GRIDLAYER]; i++) {
xRect *r = &xctx->rect[GRIDLAYER][i];
@ -2616,23 +2606,37 @@ int draw_images_all(void)
const char *filename;
double scalex, scaley;
png_to_byte_closure_t closure;
xEmb_image *emb_ptr;
if(xctx->sem) {
bbox_set = 1;
save_bbx1 = xctx->bbx1;
save_bby1 = xctx->bby1;
save_bbx2 = xctx->bbx2;
save_bby2 = xctx->bby2;
bbox(END, 0.0, 0.0, 0.0, 0.0);
}
if(!r->extraptr) {
setup_rect_extraptr(1, r, NULL);
}
emb_ptr = r->extraptr;
cairo_save(xctx->cairo_ctx);
cairo_save(xctx->cairo_save_ctx);
/* read PNG from in-memory buffer ... */
if(r->data && r->data_size) {
closure.buffer = r->data;
if(emb_ptr && emb_ptr->data && emb_ptr->data_size) {
closure.buffer = emb_ptr->data;
closure.pos = 0;
closure.size = r->data_size; /* should not be necessary */
closure.size = emb_ptr->data_size; /* should not be necessary */
image = cairo_image_surface_create_from_png_stream(png_reader, &closure);
dbg(1, "draw_images_all(): length1 = %d\n", closure.pos);
/* ... or read PNG from image_data attribute */
} else if( (attr = get_tok_value(r->prop_ptr, "image_data", 0))[0] ) {
r->data = base64_decode(attr, strlen(attr), &r->data_size);
closure.buffer = r->data;
emb_ptr->data = base64_decode(attr, strlen(attr), &emb_ptr->data_size);
closure.buffer = emb_ptr->data;
closure.pos = 0;
closure.size = r->data_size; /* should not be necessary */
closure.size = emb_ptr->data_size; /* should not be necessary */
image = cairo_image_surface_create_from_png_stream(png_reader, &closure);
dbg(1, "draw_images_all(): length2 = %d\n", closure.pos);
/* ... or read PNG from file (image attribute) */
@ -2647,10 +2651,10 @@ int draw_images_all(void)
closure.pos = 0;
cairo_surface_write_to_png_stream(image, png_writer, &closure);
dbg(1, "draw_images_all(): length3 = %d\n", closure.pos);
r->data = closure.buffer;
r->data_size = closure.pos;
emb_ptr->data = closure.buffer;
emb_ptr->data_size = closure.pos;
/* put base64 encoded data to rect image_data attrinute */
image_data = base64_encode(r->data, r->data_size, &olength);
image_data = base64_encode(emb_ptr->data, emb_ptr->data_size, &olength);
my_realloc(1466, &image_data, olength + 1);
image_data[olength] = '\0';
my_strdup2(1473, &r->prop_ptr, subst_token(r->prop_ptr, "image_data", image_data));
@ -2676,17 +2680,17 @@ int draw_images_all(void)
cairo_surface_destroy(image);
cairo_restore(xctx->cairo_ctx);
cairo_restore(xctx->cairo_save_ctx);
if(bbox_set) {
xctx->bbx1 = save_bbx1;
xctx->bby1 = save_bby1;
xctx->bbx2 = save_bbx2;
xctx->bby2 = save_bby2;
xctx->sem = 1;
bbox(SET, 0.0, 0.0, 0.0, 0.0);
}
}
}
}
if(bbox_set) {
xctx->bbx1 = save_bbx1;
xctx->bby1 = save_bby1;
xctx->bbx2 = save_bbx2;
xctx->bby2 = save_bby2;
xctx->sem = 1;
bbox(SET, 0.0, 0.0, 0.0, 0.0);
}
#endif
return 0;
}

View File

@ -434,9 +434,8 @@ static void edit_rect_property(int x)
(char *) tclgetvar("retval"));
}
if(xctx->rect[c][n].data) { /* used for images, clear so will be recreated from image attr */
my_free(1465, &xctx->rect[c][n].data);
xctx->rect[c][n].data_size = 0;
if(xctx->rect[c][n].extraptr) { /* used for images, clear so will be recreated from image attr */
setup_rect_extraptr(0, &xctx->rect[c][n], NULL);
}
flags = get_tok_value(xctx->rect[c][n].prop_ptr,"flags",0);
if( strcmp(flags, "") ) {

View File

@ -307,10 +307,8 @@ void mem_push_undo(void)
xctx->uslot[slot].bptr[c][i] = xctx->rect[c][i];
xctx->uslot[slot].bptr[c][i].prop_ptr = NULL;
my_strdup(185, &xctx->uslot[slot].bptr[c][i].prop_ptr, xctx->rect[c][i].prop_ptr);
if(xctx->rect[c][i].data && xctx->rect[c][i].data_size) {
xctx->uslot[slot].bptr[c][i].data_size = xctx->rect[c][i].data_size;
xctx->uslot[slot].bptr[c][i].data = my_malloc(1469, xctx->rect[c][i].data_size);
memcpy(xctx->uslot[slot].bptr[c][i].data, xctx->rect[c][i].data, xctx->rect[c][i].data_size);
if(xctx->rect[c][i].extraptr) {
setup_rect_extraptr(2, &xctx->uslot[slot].bptr[c][i], &xctx->rect[c][i]);
}
}
/* arcs */
@ -534,10 +532,8 @@ void mem_pop_undo(int redo, int set_modify_status)
xctx->rect[c][i] = xctx->uslot[slot].bptr[c][i];
xctx->rect[c][i].prop_ptr = NULL;
my_strdup(205, &xctx->rect[c][i].prop_ptr, xctx->uslot[slot].bptr[c][i].prop_ptr);
if(xctx->uslot[slot].bptr[c][i].data && xctx->uslot[slot].bptr[c][i].data_size) {
xctx->rect[c][i].data_size = xctx->uslot[slot].bptr[c][i].data_size;
xctx->rect[c][i].data = my_malloc(1468, xctx->uslot[slot].bptr[c][i].data_size);
memcpy(xctx->rect[c][i].data, xctx->uslot[slot].bptr[c][i].data, xctx->uslot[slot].bptr[c][i].data_size);
if(xctx->uslot[slot].bptr[c][i].extraptr) {
setup_rect_extraptr(2, &xctx->rect[c][i], &xctx->uslot[slot].bptr[c][i]);
}
}
/* arcs */

View File

@ -145,10 +145,7 @@ void check_collapsing_objects()
if(xctx->rect[c][i].x1==xctx->rect[c][i].x2 || xctx->rect[c][i].y1 == xctx->rect[c][i].y2)
{
my_free(815, &xctx->rect[c][i].prop_ptr);
if(xctx->rect[c][i].data) {
my_free(1471, &xctx->rect[c][i].data);
xctx->rect[c][i].data_size = 0;
}
setup_rect_extraptr(0, &xctx->rect[c][i], NULL);
found=1;
j++;
continue;
@ -876,10 +873,8 @@ void copy_objects(int what)
storeobject(-1, xctx->rx1+xctx->deltax, xctx->ry1+xctx->deltay,
xctx->rx2+xctx->deltax, xctx->ry2+xctx->deltay,xRECT, c, SELECTED, xctx->rect[c][n].prop_ptr);
l = xctx->rects[c] - 1;
if(xctx->rect[c][n].data && xctx->rect[c][n].data_size) {
xctx->rect[c][l].data_size = xctx->rect[c][n].data_size;
xctx->rect[c][l].data = my_malloc(1470, xctx->rect[c][n].data_size);
memcpy(xctx->rect[c][l].data, xctx->rect[c][n].data, xctx->rect[c][n].data_size);
if(xctx->rect[c][n].extraptr) {
setup_rect_extraptr(2, &xctx->rect[c][l], &xctx->rect[c][n]);
}
bbox(ADD, xctx->rect[c][l].x1, xctx->rect[c][l].y1, xctx->rect[c][l].x2, xctx->rect[c][l].y2);
break;
@ -1097,7 +1092,7 @@ void move_objects(int what, int merge, double dx, double dy)
set_modify(1);
/* no undo push for MERGE ad PLACE, already done before */
if( !xctx->kissing && !(xctx->ui_state & (STARTMERGE | PLACE_SYMBOL | PLACE_TEXT)) ) {
dbg(0, "move_objects(): push undo state\n");
dbg(1, "move_objects(): push undo state\n");
xctx->push_undo();
}
xctx->ui_state &= ~PLACE_SYMBOL;

View File

@ -111,8 +111,7 @@ void merge_box(FILE *fd)
return;
}
ptr[i].prop_ptr=NULL;
ptr[i].data=NULL;
ptr[i].data_size=0;
ptr[i].extraptr=NULL;
RECTORDER(ptr[i].x1, ptr[i].y1, ptr[i].x2, ptr[i].y2);
ptr[i].sel=0;
load_ascii_string( &ptr[i].prop_ptr, fd);

View File

@ -779,8 +779,7 @@ static void load_box(FILE *fd)
return;
}
RECTORDER(ptr[i].x1, ptr[i].y1, ptr[i].x2, ptr[i].y2);
ptr[i].data=NULL;
ptr[i].data_size=0;
ptr[i].extraptr=NULL;
ptr[i].prop_ptr=NULL;
ptr[i].sel=0;
load_ascii_string( &ptr[i].prop_ptr, fd);

View File

@ -218,6 +218,7 @@ static void del_rect_line_arc_poly(void)
j++;
bbox(ADD, xctx->rect[c][i].x1, xctx->rect[c][i].y1, xctx->rect[c][i].x2, xctx->rect[c][i].y2);
my_free(928, &xctx->rect[c][i].prop_ptr);
setup_rect_extraptr(0, &xctx->rect[c][i], NULL);
set_modify(1);
continue;
}

View File

@ -308,8 +308,7 @@ void storeobject(int pos, double x1,double y1,double x2,double y2,
xctx->rect[rectc][n].y1=y1;
xctx->rect[rectc][n].y2=y2;
xctx->rect[rectc][n].prop_ptr=NULL;
xctx->rect[rectc][n].data=NULL;
xctx->rect[rectc][n].data_size=0;
xctx->rect[rectc][n].extraptr=NULL;
my_strdup(413, &xctx->rect[rectc][n].prop_ptr, prop_ptr);
xctx->rect[rectc][n].sel=sel;
if(prop_ptr && (dash = get_tok_value(prop_ptr,"dash",0))[0]) {

View File

@ -395,6 +395,12 @@ typedef struct
short bus;
} xLine;
typedef struct
{
unsigned char *data;
size_t data_size;
} xEmb_image;
typedef struct
{
double x1;
@ -403,8 +409,7 @@ typedef struct
double y2;
unsigned short sel;
char *prop_ptr;
void *data; /* generic data pointer (images) */
size_t data_size; /* generic data pointer (images) */
void *extraptr; /* generic data pointer (images) */
short dash;
/* bit0=1 for graph function, bit1=1 for unlocked x axis
* bit10: image embedding (png)
@ -994,6 +999,7 @@ extern int cli_opt_load_initfile;
extern Xschem_ctx *xctx;
/* FUNCTIONS */
extern int setup_rect_extraptr(int what, xRect *drptr, xRect *srptr);
extern unsigned char *base64_decode(const char *data, size_t input_length, size_t *output_length);
extern char *base64_encode(const unsigned char *data, size_t input_length, size_t *output_length);
extern int get_raw_index(const char *node);

File diff suppressed because one or more lines are too long