fix clipping for image redraw speed-up, embedded raster png/jpg in svg exports

This commit is contained in:
Stefan Frederik 2022-01-23 22:41:24 +01:00
parent c8ec7a77f2
commit 348802c655
3 changed files with 48 additions and 29 deletions

View File

@ -2416,11 +2416,10 @@ static cairo_status_t png_writer(void *in_closure, const unsigned char *in_data,
int draw_images_all(void)
{
#if HAS_CAIRO==1
int i, bbox_set = 0, w, h;
double x, y, rw, rh, rescaled = 0;
int ret = 0, i, w, h;
double x, y, rw, rh;
double sx1, sy1, sx2, sy2, alpha;
const char *ptr;
int save_bbx1, save_bby1, save_bbx2, save_bby2;
char filename[PATH_MAX];
if(xctx->draw_single_layer==-1 || GRIDLAYER == xctx->draw_single_layer) {
@ -2436,14 +2435,6 @@ int draw_images_all(void)
my_strncpy(filename, get_tok_value(r->prop_ptr, "image", 0), S(filename));
my_strdup(1484, &filter, get_tok_value(r->prop_ptr, "filter", 0));
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);
}
/* screen position */
sx1=X_TO_SCREEN(r->x1);
sy1=Y_TO_SCREEN(r->y1);
@ -2477,7 +2468,7 @@ int draw_images_all(void)
closure.pos = 0;
closure.size = data_size; /* should not be necessary */
emb_ptr->image = cairo_image_surface_create_from_png_stream(png_reader, &closure);
if(closure.buffer == NULL) dbg(0, "draw_images_all(): null closure.buffer, i=%d\n", i);
if(closure.buffer == NULL) dbg(0, "draw_images_all(): image creation failed, n=%d\n", i);
my_free(1467, &closure.buffer);
dbg(1, "draw_images_all(): length2 = %d\n", closure.pos);
/* ... or read PNG from file (image attribute) */
@ -2524,12 +2515,12 @@ int draw_images_all(void)
my_free(1474, &image_data);
if(cairo_surface_status(emb_ptr->image) != CAIRO_STATUS_SUCCESS) return 1;
if(cairo_surface_status(emb_ptr->image) != CAIRO_STATUS_SUCCESS) {ret = 1; continue;}
dbg(1, "draw_images_all(): length3 = %d\n", closure.pos);
} else {
return 1;
{ret = 1; continue;}
}
if(cairo_surface_status(emb_ptr->image) != CAIRO_STATUS_SUCCESS) return 1;
if(cairo_surface_status(emb_ptr->image) != CAIRO_STATUS_SUCCESS) {ret = 1; continue;}
ptr = get_tok_value(r->prop_ptr, "alpha", 0);
alpha = 1.0;
if(ptr[0]) alpha = atof(ptr);
@ -2543,7 +2534,6 @@ int draw_images_all(void)
r->y2 = r->y1 + h;
scalex = xctx->mooz;
scaley = xctx->mooz;
rescaled = 1;
} else { /* resize image to fit in rectangle */
rw = abs(r->x2 - r->x1);
rh = abs(r->y2 - r->y1);
@ -2554,31 +2544,30 @@ int draw_images_all(void)
cairo_translate(xctx->cairo_save_ctx, x, y);
cairo_scale(xctx->cairo_save_ctx, scalex, scaley);
cairo_set_source_surface(xctx->cairo_save_ctx, emb_ptr->image, 0. , 0.);
cairo_rectangle(xctx->cairo_save_ctx, 0, 0, w , h );
/* cairo_fill(xctx->cairo_save_ctx);
* cairo_stroke(xctx->cairo_save_ctx); */
cairo_clip(xctx->cairo_save_ctx);
cairo_paint_with_alpha(xctx->cairo_save_ctx, alpha);
}
if(xctx->draw_window) {
cairo_translate(xctx->cairo_ctx, x, y);
cairo_scale(xctx->cairo_ctx, scalex, scaley);
cairo_set_source_surface(xctx->cairo_ctx, emb_ptr->image, 0. , 0.);
cairo_rectangle(xctx->cairo_ctx, 0, 0, w , h );
/* cairo_fill(xctx->cairo_ctx);
* cairo_stroke(xctx->cairo_ctx); */
cairo_clip(xctx->cairo_ctx);
cairo_paint_with_alpha(xctx->cairo_ctx, alpha);
}
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;
if(rescaled) bbox(ADD, r->x1, r->y1, r->x2, r->y2);
bbox(SET, 0.0, 0.0, 0.0, 0.0);
}
my_free(1486, &filter);
}
}
}
#endif
return 0;
return ret;
}
void draw(void)

View File

@ -551,6 +551,28 @@ static void fill_svg_colors()
}
void svg_embedded_image(int i)
{
xRect *r = &xctx->rect[GRIDLAYER][i];
const char *ptr;
double x1,y1,x2,y2;
int jpg = 0;
x1=X_TO_SVG(r->x1);
y1=Y_TO_SVG(r->y1);
x2=X_TO_SVG(r->x2);
y2=Y_TO_SVG(r->y2);
ptr = get_tok_value(r->prop_ptr, "image_data", 0);
if(ptr[0]) {
if(!strncmp(ptr, "/9j/4", 5)) jpg = 1; /* jpeg base64 header (30 bits checked) */
fprintf(fd, "<image x=\"%g\" y=\"%g\" width=\"%g\" height=\"%g\" "
"xlink:href=\"data:image/%s;base64,%s\"/>\n",
x1, y1, x2 - x1, y2 - y1, jpg ? "jpg" : "png", ptr);
}
}
void svg_draw(void)
{
double dx, dy;
@ -647,6 +669,7 @@ void svg_draw(void)
#endif
fprintf(fd, "<svg xmlns=\"http://www.w3.org/2000/svg\""
" xmlns:xlink=\"http://www.w3.org/1999/xlink\""
" width=\"%g\" height=\"%g\" version=\"1.1\">\n", dx, dy);
fprintf(fd, "<style type=\"text/css\">\n"); /* use css stylesheet 20121119 */
@ -713,7 +736,9 @@ void svg_draw(void)
xctx->line[c][i].x2, xctx->line[c][i].y2, xctx->line[c][i].dash);
for(i=0;i<xctx->rects[c];i++)
{
if(c != GRIDLAYER || !(xctx->rect[c][i].flags & 1) ) {
if(c == GRIDLAYER && (xctx->rect[c][i].flags & 1024) ) {
svg_embedded_image(i);
} else if(c != GRIDLAYER || !(xctx->rect[c][i].flags & 1) ) {
svg_filledrect(c, xctx->rect[c][i].x1, xctx->rect[c][i].y1,
xctx->rect[c][i].x2, xctx->rect[c][i].y2, xctx->rect[c][i].dash);
}

View File

@ -895,8 +895,13 @@ const char *subst_token(const char *s, const char *tok, const char *new_val)
if(!new_val_copy[0]) new_val_copy = "\"\"";
tmp = strlen(new_val_copy) + strlen(tok) + 2;
STR_ALLOC(&result, tmp + result_pos, &size);
/* result_pos guaranteed to be > 0 */
my_snprintf(result + result_pos - 1, size, " %s=%s", tok, new_val_copy );
if(result_pos > 1 && (result[result_pos - 2] == ' ' || result[result_pos - 2] == '\n')) {
/* result_pos guaranteed to be > 0 */
my_snprintf(result + result_pos - 1, size, "%s=%s", tok, new_val_copy );
} else {
/* result_pos guaranteed to be > 0 */
my_snprintf(result + result_pos - 1, size, "\n%s=%s", tok, new_val_copy );
}
}
}
dbg(2, "subst_token(): returning: %s\n",result);