Dear Moazin,

Please browse the attached SVG: which paints a big blue square (1024 x 1024),
and clip small circle at the center of it (r=64). How do you evaluate the
bitmap_left and bitmap_top? bitmap_left is 512 - 64 = 448? Or, bitmap_left is 0?

Moazin Khatri wrote:
> `Resvg' works with two graphic backends, `cairo' and `qt', so it would be 
> interesting to look at how they calculate the bounding box. From a quick 
> look, it looks like they use some recursive mechanism to calculate the 
> bounding box of each element and then expanding it with every iteration until 
> the final bounding box is calculated.

Yes, yes, it is good starting point for the implementers.

If we focus to the simple SVG consists from path objects (path, polygon,
polyline, ellipse, rectangle etc etc), the task is already completed. It would
not be so difficult in SVG Native Viewer, I hope.

But, if we want the renderer to calculate the bitmap_left of attached SVG as
448, instead of 0, finding a boundingbox without real drawing becomes difficult
task. If we deal a SVG including the raster image with alpha channel (and if we
hope as the transparent pixel in embedded image should be dealt as un-inked), it
would become more harder.

I confirmed that resvg_get_image_bbox() evaluates bitmap_left of the attached
SVG as 0 (the returned bbox is 1024 x 1024, instead of 64 x 64).
And, I confirmed that even cairo_recording_surface_ink_extents() evaluates the
bitmap_left as 0, either! Sigh.

Regards,
mpsuzuki

P.S.
I attached a program I used for the confirmation (it's a modified version of
resvg's example.c, to avoid GTK+).
#include <stdio.h>
#include <stdlib.h>
#include <resvg.h>
#include <cairo.h>

static resvg_render_tree *tree = NULL;
static resvg_options opt;

void
draw_cb (const char *path)
{
    if (!tree || !path)
        return;

    cairo_rectangle_t docExtents = { 0, 0, 0, 0 };
    resvg_rect viewBox = resvg_get_image_viewbox(tree);
    docExtents.x = viewBox.x;
    docExtents.y = viewBox.y;
    docExtents.width = viewBox.width;
    docExtents.height = viewBox.height;
    cairo_surface_t* cairoSurface = cairo_recording_surface_create( CAIRO_CONTENT_COLOR_ALPHA, &docExtents );
    cairo_t* cr = cairo_create( cairoSurface );

    resvg_size svgSize = { viewBox.width, viewBox.height };
    resvg_cairo_render_to_canvas(tree, &opt, svgSize, cr);
    cairo_destroy( cr );

    cairo_surface_write_to_png( cairoSurface, path );

    double x0, y0, w, h;
    cairo_recording_surface_ink_extents( cairoSurface, &x0, &y0, &w, &h);
    printf("cairo-ink-extent: {%f, %f, %f, %f}\n", x0, y0, w, h);

    cairo_surface_destroy( cairoSurface );
}


void
print_bbox()
{
    resvg_rect viewBox = resvg_get_image_viewbox(tree);
 
    printf("viewBox: {%f, %f, %f, %f}\n", viewBox.x, viewBox.y, viewBox.width, viewBox.height);


    resvg_rect boundingBox;
    resvg_get_image_bbox(tree, &boundingBox);

    printf("boundingBox: {%f, %f, %f, %f}\n", boundingBox.x, boundingBox.y, boundingBox.width, boundingBox.height);
}


void
parse_doc (const char *path)
{
    resvg_init_options(&opt);
    opt.path = path;
    opt.font_family = "Liberation Sans";
    opt.languages = "en";

    int err = resvg_parse_tree_from_file(path, &opt, &tree);
    if (err != RESVG_OK) {
        fprintf(stderr, "Error id: %i\n", err);
        abort();
    }
}

int
main(int argc, char **argv)
{
    if (argc < 3)
       abort();

    parse_doc(argv[1]);
    print_bbox();
    draw_cb(argv[2]);
}
_______________________________________________
Freetype-devel mailing list
Freetype-devel@nongnu.org
https://lists.nongnu.org/mailman/listinfo/freetype-devel

Reply via email to