RazrFalcon / resvg

An SVG rendering library.
Mozilla Public License 2.0
2.76k stars 221 forks source link

clip paths are incorrect with transform #642

Open gmeeker opened 1 year ago

gmeeker commented 1 year ago

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).

RazrFalcon commented 1 year ago

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 commented 1 year ago

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.

gmeeker commented 1 year ago

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 commented 1 year ago

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).

RazrFalcon commented 1 year ago

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...