I'm trying to implement this example written in C with C Tk API.
My objective is to try to use this library to transform an svg file into a photo Tk to be read in frame Tk. Below is my svg file :
<svg id="svg1" viewBox="0 0 100 100" xmlns="http://www.w3.org/2000/svg">
<circle r="32" cx="35" cy="65" fill="#F00" opacity="0.5"/>
<circle r="32" cx="65" cy="65" fill="#0F0" opacity="0.5"/>
<circle r="32" cx="50" cy="35" fill="#00F" opacity="0.5"/>
</svg>
and my C code :
Tk_PhotoHandle source;
unsigned char *imgData;
// PhotoObj : set photo [image create photo]; # tcl code
// FileObj : file.svg
source = Tk_FindPhoto(interp, Tcl_GetString(PhotoObj));
if (source == NULL) {
Tcl_SetResult(interp, "photo not found", TCL_STATIC);
return TCL_ERROR;
}
char *sp = Tcl_GetString(FileObj);
resvg_init_log;
resvg_options *opt = resvg_options_create();
resvg_options_load_system_fonts(opt);
resvg_render_tree *tree;
int err = resvg_parse_tree_from_file(sp, opt, &tree);
resvg_options_destroy(opt);
if (err != RESVG_OK) {
printf("Error id: %i\n", err);
return TCL_ERROR;
}
resvg_size size = resvg_get_image_size(tree);
int width = (int)size.width;
int height = (int)size.height;
imgData = (unsigned char *)Tcl_Alloc(width*height*4);
if (imgData == NULL) {
Tcl_SetResult(interp, "cannot alloc image buffer", TCL_STATIC);
return TCL_ERROR;
}
resvg_render(tree, resvg_transform_identity(), width, height, imgData);
Tk_PhotoImageBlock block;
Tk_PhotoGetImage(source, &block);
block.pixelPtr = imgData;
block.width = width;
block.height = height;
block.pitch = width * 4;
block.pixelSize = 4;
block.offset[0] = 0;
block.offset[1] = 1;
block.offset[2] = 2;
block.offset[3] = 3;
if (Tk_PhotoSetSize(interp, source, width, height) != TCL_OK) {
return TCL_ERROR;
}
Tk_PhotoPutBlock(interp, source, &block, 0, 0, width, height, TK_PHOTO_COMPOSITE_SET);
resvg_tree_destroy(tree);
return TCL_OK;
.
As you can see, the colours in the left-hand svg are not the same as those in the Tk right image.
Maybe the problem comes from my imgData variable, the author in his example seems to be retransforming the data for a cairo surface. My knowledge of image transformation is fairly limited, so I don't know what to do on the Tk side.
I've finally gotten around to testing this properly; I created an SVG file with exactly the contents you suggested, and then ran this script:
That reported that I ran
Tcl: 9.0a4, Tk: 9.0b1(yes, a weird mix; my development machine is not in wholly consistent state)The screenshot of the output is this:
And the generated PNG is this:
I also looked at all images using several image viewing tools (browsers). The result of this experiment is that I know that Tk rendering the SVG correctly (or at least very close to it), both with a light and a dark background, and that the underlying image model has the correct data because the PNG (with transparency) is being written correctly. This is a tremendous relief to me!
So what's going on with your problem? Well, I'm using the built-in SVG renderer in Tk 8.7 (9.0 is essentially the same) that is fully aware of the photo image's internal RGBA model, and you're using some other SVG renderer (resvg) that seems to make assumptions about what the background colour of the image should be. Those assumptions (which appear to be slanted towards the darker end) are obviously wrong; photos are full RGBA and the compositing with the background can be left to Tk.
I'm not sure whether this is a fault in resvg or in how you are using it; it's entirely possible that a suitable option would make it behave correctly. I don't know it well enough to say for sure.
Thank you for asking this question! It's prompted me to test Tk in this area a bit more thoroughly; I'm now reasonably sure that Tk is doing the right thing. I had wondered because we definitely have had some reported problems with this in the past, yet they've been frustratingly difficult to hunt down! This case was simple enough that I could cross-check it properly and understand that the results were definitely as expected.
I've no control over what third-party code does, and I'm not going to speculate on how to mend it.