[cairo] How to get extents of transformed graphics

Bill Spitzak spitzak at gmail.com
Fri Sep 9 15:38:09 UTC 2022


Not sure exactly what you are trying to do, but this is probably what you
want (this also assumes x2>x1 and y2>y1):

width = ceil(x2 * 4.6) - floor(x1 * 4.6);
height = ceil(y2 * 4.6) - floor(y1 * 4.6);

The reason for the ceil and floor is so the fractional-covered pixels are
rounded out to the result. You have to do this after you convert to pixels
which is what multiplying by 4.6 is doing (?).


On Fri, Sep 9, 2022 at 7:16 AM Andreas Falkenhahn <andreas at falkenhahn.com>
wrote:

> I can fix the issue by adding 2 to "height" like so:
>
>         width = fabs(ceil(x2) - floor(x1));
>         height = fabs(ceil(y2) - floor(y1));
>
>         width = ceil(width * 4.6);
>         height = ceil(height * 4.6) + 2;
>
> But this feels very kludgy and probably only works for my specific case
> and not for any arbitrary transformation values.
>
> Is there really no general solution to this problem? IMHO it's a rather
> common thing to do and I'm a bit puzzled why this should be so difficult to
> solve...
>
> On 08.09.2022 at 19:24 Andreas Falkenhahn wrote:
>
> > I've tried this:
>
> >         width = fabs(x2 - floor(x1));
> >         height = fabs(y2 - floor(y1));
>
> >         width = ceil(width * 4.6);
> >         height = ceil(height * 4.6);
>
> > Still cuts off a line of the "C" shape. I've also tried this:
>
> >         width = fabs(ceil(x2) - floor(x1));
> >         height = fabs(ceil(y2) - floor(y1));
>
> >         width = ceil(width * 4.6);
> >         height = ceil(height * 4.6);
>
> > No success either. A line is cut off.
>
> > Any more ideas? You can find my test program below...
>
> > On 08.09.2022 at 19:03 Behdad Esfahbod wrote:
>
> >> Try flooring x1,y1 before subtracting them from x2,y2 for computing the
> size of your surface.
>
>
> >> behdad
> >> http://behdad.org/
>
> >> On Thu, Sep 8, 2022 at 10:21 AM Andreas Falkenhahn <
> andreas at falkenhahn.com> wrote:
>
> >> Is there really nobody who knows how to solve this? There surely
> >> must be a way to find out the *exact* extents of transformed
> >> graphics? The idea is to find out the exact dimensions in order to
> >> allocate a Cairo surface that *exactly* matches the size of the path.
> >>
> >>  On 28.08.2022 at 21:47 Andreas Falkenhahn wrote:
> >>
>  >>> Hi,
> >>
>  >>> is there any way to get the *exact* extents of transformed
>  >>> graphics? AFAICS, cairo_fill_extents() is in user coordinates, i.e.
>  >>> it doesn't take any transformation settings into account. So I've
>  >>> tried to apply the transformation manually to what I get from
>  >>> cairo_fill_extents() but I don't seem to get it 100% right. It looks
>  >>> like one row is missing at the bottom.
> >>
>  >>> This is what I've tried:
> >>
>  >>>         cairo_t *cr;
>  >>>         cairo_surface_t *surface;
>  >>>         cairo_matrix_t cm;
>  >>>         int k;
>  >>>         double tx = 0, ty = 0;
>  >>>         double x1, y1, x2, y2;
>  >>>
>  >>>         surface = cairo_image_surface_create(CAIRO_FORMAT_A8, 1000,
> 1000);
>  >>>         cr = cairo_create(surface);
> >>
>  >>>         for(k = 0; k < 2; k++) {
>  >>>
>  >>>                 cairo_new_path(cr);
>  >>>                 cairo_move_to(cr, tx, ty);
>  >>>                 cairo_set_font_size(cr, 100);
>  >>>                 cairo_text_path(cr, "C");
>  >>>
>  >>>                 if(!k) {
>  >>>
>  >>>                         double width, height;
>  >>>
>  >>>                         cairo_fill_extents(cr, &x1, &y1, &x2, &y2);
>  >>>
>  >>>                         tx = -x1;
>  >>>                         ty = -y1;
>  >>>
>  >>>                         width = fabs(x2 - x1);
>  >>>                         height = fabs(y2 - y1);
> >>
>  >>>                         width = ceil(width * 4.6);
>  >>>                         height = ceil(height * 4.6);
>  >>>
>  >>>                         cairo_destroy(cr);
>  >>>                         cairo_surface_destroy(surface);
>  >>>
>  >>>                         surface =
>  >>> cairo_image_surface_create(CAIRO_FORMAT_A8, width, height);
>  >>>                         cr = cairo_create(surface);
>  >>>
>  >>>                         cairo_matrix_init(&cm, 4.6, 0, 0, 4.6, 0, 0);
>  >>>                         cairo_set_matrix(cr, &cm);
>  >>>                 }
>  >>>         }
>  >>>
>  >>>         cairo_fill(cr);
> >>
>  >>>         cairo_surface_flush(surface);
>  >>>         cairo_surface_write_to_png(surface, "tmp.png");
>  >>>
>  >>>         cairo_destroy(cr);
>  >>>         cairo_surface_destroy(surface);
> >>
>  >>> I'm attaching the resulting image. As you can see, there's at least
>  >>> one row of the "C" shape missing at the bottom of the image.
> >>
>  >>> Any ideas how to get this right? Is this some sort of floating
>  >>> point inaccuracy and should I just add 1 to width/height to solve
>  >>> this or am I doing something wrong here and there is a better way?
> >>
> >>
> >>
> >>  --
> >>  Best regards,
> >>   Andreas Falkenhahn                            mailto:
> andreas at falkenhahn.com
> >>
> >>
>
>
>
>
> --
> Best regards,
>  Andreas Falkenhahn                            mailto:
> andreas at falkenhahn.com
>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.cairographics.org/archives/cairo/attachments/20220909/11f39176/attachment.htm>


More information about the cairo mailing list