[cairo] How to get extents of transformed graphics

Andreas Falkenhahn andreas at falkenhahn.com
Fri Sep 9 14:17:58 UTC 2022


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



More information about the cairo mailing list