resvg icon indicating copy to clipboard operation
resvg copied to clipboard

clip paths are incorrect with transform

Open gmeeker opened this issue 1 year ago • 5 comments

I'm trying to render tiles of the full SVG. It works fine for many files but breaks for files with clip paths. Try the attached SVG with a modified version of the cairo example:

diff --git a/crates/c-api/examples/cairo/example.c b/crates/c-api/examples/cairo/example.c
index 23a3b45a..ab3bc558 100644
--- a/crates/c-api/examples/cairo/example.c
+++ b/crates/c-api/examples/cairo/example.c
@@ -29,6 +29,7 @@ int main(int argc, char **argv)
     resvg_size size = resvg_get_image_size(tree);
     int width = (int)size.width;
     int height = (int)size.height;
+    height = 270;
 
     cairo_surface_t *surface = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, width, height);
 
@@ -37,7 +38,9 @@ int main(int argc, char **argv)
 
     unsigned char *surface_data = cairo_image_surface_get_data(surface);
 
-    resvg_render(tree, resvg_transform_identity(), width, height, (char*)surface_data);
+    resvg_transform transform = resvg_transform_identity();
+    transform.f = -height * 3;
+    resvg_render(tree, transform, width, height, (char*)surface_data);
 
     /* RGBA -> BGRA */
     for (int i = 0; i < width * height * 4; i += 4)
make
LD_LIBRARY_PATH=../../../../target/debug ./example clipPath.svg clipPath.png

This still works if the offset is 0 or if the full height is used, but the combination of offset, crop, and clip path cause most of the image to disappear.

clipPath clipPath

It seems to be an old bug (at least present in 0.33.0).

gmeeker avatar Jul 08 '23 04:07 gmeeker

Yes, we do not support this use case right now. It has nothing to do with clip paths.

Basically, the problem is that the renderer expects the image/pixmap size to be proportional to the SVG size. You are overwriting it and it trips the internal logic. Will see what can be done about it.

RazrFalcon avatar Jul 10 '23 11:07 RazrFalcon

PS: rendering a part of SVG in general is a very bad idea. And in many cases it wouldn't even be faster. You're better off rendering on a huge image and then slicing it up.

RazrFalcon avatar Jul 10 '23 11:07 RazrFalcon

I thought this was related to the cropped height, but I found a better test case. This file doesn't render correctly (no C API required) but looks fine in Chrome. I've been trying to reproduce this since I reported #638 and I suspect they might be related.

resvg clipPath2.svg clipPath2.png

clipPath2 clipPath2

gmeeker avatar Jul 10 '23 17:07 gmeeker

P.S. I know the tiling isn't supported but other than this issue (which seems to be something else?) it does seem to render faster (up to 4 threads for the files I'm using). Obviously it's pretty wasteful from an energy consumption perspective, but it helps for our very specific use case. Most users would probably just render multiple files in parallel but there are reasons we need each frame to render faster (that aren't worth going into here).

gmeeker avatar Jul 10 '23 17:07 gmeeker

Yeah... that's a bug. You can try using v0.32 for now. v0.33 had a new rendering logic which would take forever to polish. SVG is a horrible file format...

RazrFalcon avatar Jul 10 '23 18:07 RazrFalcon