update svgdraw and psprint to recognize svg embedded images. svgdraw exports it as embedded svg

This commit is contained in:
stefan schippers 2024-10-28 18:55:13 +01:00
parent 76c1425180
commit c342a1c41f
4 changed files with 52 additions and 18 deletions

View File

@ -4229,7 +4229,7 @@ int edit_image(int what, xRect *r)
* The return value is a pointer to the beginning of the sub-string, or
* NULL if the substring is not found.
*/
static void *my_memmem(const void *haystack, size_t hlen, const void *needle, size_t nlen)
void *my_memmem(const void *haystack, size_t hlen, const void *needle, size_t nlen)
{
int needle_first;
const char *p = haystack;

View File

@ -85,14 +85,15 @@ static int ps_embedded_image(xRect* r, double x1, double y1, double x2, double y
unsigned char *ptr = NULL;
int invertImage;
unsigned char* ascii85EncodedJpeg;
const char* attr;
char *attr = NULL;
unsigned char *buffer = NULL;
cairo_surface_t *surface = NULL, *orig_sfc = NULL;
xEmb_image *emb_ptr;
unsigned char* jpgData = NULL;
size_t fileSize = 0;
int quality=40;
const char *quality_attr;
size_t oLength, attr_len;
const char *quality_attr, *filter;
size_t oLength, attr_len, buffer_size;
cairo_t *ct;
double sx1, sy1, sx2, sy2;
@ -113,17 +114,26 @@ static int ps_embedded_image(xRect* r, double x1, double y1, double x2, double y
quality_attr = get_tok_value(r->prop_ptr, "jpg_quality", 0);
if(quality_attr[0]) quality = atoi(quality_attr);
}
attr = get_tok_value(r->prop_ptr, "image_data", 0);
attr_len = strlen(attr);
attr_len = my_strdup2(_ALLOC_ID_, &attr, get_tok_value(r->prop_ptr, "image_data", 0));
filter = get_tok_value(r->prop_ptr, "filter", 0);
buffer = base64_decode(attr, attr_len, &buffer_size);
if(attr_len > 5) {
if(!strncmp(attr, "/9j/", 4)) jpg = 1;
else if(!strncmp(attr, "iVBOR", 5)) jpg = 0;
if(!strncmp(attr, "/9j/", 4)) jpg = 1; /* jpg */
else if(!strncmp(attr, "iVBOR", 5)) jpg = 0; /* png */
else if(my_memmem(buffer, buffer_size, "<svg", 4) &&
my_memmem(buffer, buffer_size, "xmlns", 5)) {
if(filter) {
jpg = 2; /* svg */
}
}
else jpg = -1; /* some invalid data */
} else {
jpg = -1;
}
emb_ptr = r->extraptr;
if(jpg == -1 || !(emb_ptr && emb_ptr->image)) {
my_free(_ALLOC_ID_, &buffer);
my_free(_ALLOC_ID_, &attr);
return 0;
}
orig_sfc = emb_ptr->image;
@ -164,7 +174,7 @@ static int ps_embedded_image(xRect* r, double x1, double y1, double x2, double y
ptr[i + 0] = b;
}
cairo_surface_mark_dirty(surface);
if(invertImage || jpg == 0) {
if(invertImage || jpg != 1) {
cairo_image_surface_write_to_jpeg_mem(surface, &jpgData, &fileSize, quality);
} else {
jpgData = base64_decode(attr, attr_len, &fileSize);
@ -234,6 +244,8 @@ static int ps_embedded_image(xRect* r, double x1, double y1, double x2, double y
fprintf(fd, "grestore\n");
my_free(_ALLOC_ID_, &ascii85EncodedJpeg);
free(jpgData);
my_free(_ALLOC_ID_, &buffer);
my_free(_ALLOC_ID_, &attr);
#endif
return 1;
}

View File

@ -468,13 +468,16 @@ static void svg_drawgrid()
static int svg_embedded_image(xRect *r, double rx1, double ry1, double rx2, double ry2, int rot, int flip)
{
const char *attr;
char *attr = NULL;
const char *alpha_str, *filter;
size_t attr_len;
double x1, y1, x2, y2, w, h, scalex = 1.0, scaley = 1.0;
int jpg = 0;
char opacity[100];
char transform[150];
double alpha = 1.0;
unsigned char *buffer = NULL;
size_t buffer_size;
x1=X_TO_SCREEN(rx1);
y1=Y_TO_SCREEN(ry1);
@ -496,28 +499,46 @@ static int svg_embedded_image(xRect *r, double rx1, double ry1, double rx2, doub
if(flip && (rot == 0 || rot == 2)) scalex = -1.0;
else if(flip && (rot == 1 || rot == 3)) scaley = -1.0;
attr = get_tok_value(r->prop_ptr, "alpha", 0);
if(attr[0]) alpha = atof(attr);
attr = get_tok_value(r->prop_ptr, "image_data", 0);
attr_len = strlen(attr);
alpha_str = get_tok_value(r->prop_ptr, "alpha", 0);
if(alpha_str[0]) alpha = atof(alpha_str);
attr_len = my_strdup2(_ALLOC_ID_, &attr, get_tok_value(r->prop_ptr, "image_data", 0));
buffer = base64_decode(attr, attr_len, &buffer_size);
filter = get_tok_value(r->prop_ptr, "filter", 0);
if(attr_len > 5) {
if(!strncmp(attr, "/9j/", 4)) jpg = 1;
else if(!strncmp(attr, "iVBOR", 5)) jpg = 0;
else if(my_memmem(buffer, buffer_size, "<svg", 4) &&
my_memmem(buffer, buffer_size, "xmlns", 5)) {
if(filter) {
jpg = 2; /* svg */
}
}
else jpg = -1; /* some invalid data */
} else {
jpg = -1;
}
if(jpg == -1) {
my_free(_ALLOC_ID_, &buffer);
my_free(_ALLOC_ID_, &attr);
return 0;
}
my_snprintf(transform, S(transform),
"transform=\"translate(%g,%g) scale(%g,%g) rotate(%d)\"", x1, y1, scalex, scaley, rot * 90);
if(alpha == 1.0) strcpy(opacity, "");
else my_snprintf(opacity, S(opacity), "style=\"opacity:%g;\"", alpha);
fprintf(fd, "<image x=\"%g\" y=\"%g\" width=\"%g\" height=\"%g\" %s %s "
"xlink:href=\"data:image/%s;base64,%s\"/>\n",
0.0, 0.0, w, h, transform, opacity, jpg ? "jpeg" : "png", attr);
/* png jpg */
if(jpg == 0 || jpg == 1) {
fprintf(fd, "<image x=\"%g\" y=\"%g\" width=\"%g\" height=\"%g\" %s %s "
"xlink:href=\"data:image/%s;base64,%s\"/>\n",
0.0, 0.0, w, h, transform, opacity, jpg ? "jpeg" : "png", attr);
} else if(jpg == 2) { /* svg */
fprintf(fd, "<image x=\"%g\" y=\"%g\" width=\"%g\" height=\"%g\" %s %s "
"xlink:href=\"data:image/svg+xml;base64,%s\"/>\n",
0.0, 0.0, w, h, transform, opacity, attr);
}
my_free(_ALLOC_ID_, &buffer);
my_free(_ALLOC_ID_, &attr);
return 1;
}

View File

@ -1630,6 +1630,7 @@ extern char *my_free(int id, void *ptr);
extern size_t my_strcat(int id, char **, const char *);
extern size_t my_strcat2(int id, char **, const char *);
extern size_t my_mstrcat(int id, char **str, const char *append_str, ...);
extern void *my_memmem(const void *haystack, size_t hlen, const void *needle, size_t nlen);
extern char *my_itoa(int i);
extern double atof_spice(const char *s);
extern double atof_eng(const char *s); /* same as atof_spice, but recognizes 'M' as Mega and 'm' as Milli */