Groups | Search | Server Info | Login | Register


Groups > comp.graphics.misc > #545

Running into problems while trying to scale Cairo surface to take up maximum space at specific aspect ratio

From Blue-Maned_Hawk <bluemanedhawk@gmail.com>
Newsgroups comp.graphics.misc
Subject Running into problems while trying to scale Cairo surface to take up maximum space at specific aspect ratio
Date 2023-06-11 19:13 -0400
Organization A noiseless patient Spider
Message-ID <u65kfe$2r139$2@bluemanedhawk.eternal-september.org> (permalink)

Show all headers | View raw


​​Hello!

I'm looking for help with a problem i'm running into with the Cairo 
graphics library.  I want to paint a surface onto another surface (in 
this case an XLib window) in such a way that it will take up as much 
space as possible while staying at a 4:3 aspect ratio and be centered 
within the window.  However, i seemingly can't figure out the right 
parameters for cairo_scale(), and am running into issues with a 
stretched image and an image that doesn't take up the right amount of space.

Minimum example program demonstrating this behavior below; compile with 
`$CC tmp.c -lX11 -lm -lcairo`.  Rescale the window and you'll see the 
problem i'm facing.  (I am fully aware this will lead to a pixelated 
output [not visible in the example program where it's just pure white]; 
this is intentional and exactly what i want to happen.)

#include <X11/Xlib.h>
#include <cairo/cairo.h>
#include <cairo/cairo-xlib.h>
#include <stddef.h>
#include <math.h>

const int width = 640, height = 480;
const long double aspect_ratio = 4.0l/3.0l, inverse_aspect_ratio = 
3.0l/4.0l;

int main(void)
{
     Display * display = XOpenDisplay(NULL);
     int screen = DefaultScreen(display);
     Window window = XCreateSimpleWindow(display, RootWindow(display, 
screen), 10, 10, width, height, 1, BlackPixel(display, screen), 
WhitePixel(display, screen));
     XSelectInput(display, window, StructureNotifyMask);
     XMapWindow(display, window);

     cairo_surface_t * surface = cairo_xlib_surface_create(display, 
window, DefaultVisual(display, screen), width, height);
     cairo_xlib_surface_set_size(surface, width, height);
     cairo_t * root_instance = cairo_create(surface);
     cairo_surface_destroy(surface);
     surface = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, width, 
height);
     cairo_t * instance = cairo_create(surface);

     cairo_set_source_rgb(instance, 1, 1, 1);
     cairo_paint(instance);

     for (;;) {
         for (XEvent e; XPending(display) != 0; XNextEvent(display, &e))
             if (e.type == ConfigureNotify) {
                 cairo_identity_matrix(root_instance);
                 if (e.xconfigure.width < width || e.xconfigure.height < 
height) {
                     XResizeWindow(display, window, fmax(width, 
e.xconfigure.width), fmax(width, e.xconfigure.height));
 
cairo_xlib_surface_set_size(cairo_get_target(root_instance), fmax(width, 
e.xconfigure.width), fmax(height, e.xconfigure.height));
                 } else {
 
cairo_xlib_surface_set_size(cairo_get_target(root_instance), 
e.xconfigure.width, e.xconfigure.height);
                     if (e.xconfigure.width >= aspect_ratio * 
e.xconfigure.height) {
                         cairo_translate(root_instance, 
(e.xconfigure.width - e.xconfigure.height * aspect_ratio) / 2, 0);
                         cairo_scale(root_instance, (e.xconfigure.height 
* aspect_ratio) / width, e.xconfigure.height / height);
                     } else {
                         cairo_translate(root_instance, 0, 
(e.xconfigure.height - e.xconfigure.width * inverse_aspect_ratio) / 2);
                         cairo_scale(root_instance, e.xconfigure.width / 
width, (e.xconfigure.height * inverse_aspect_ratio) / height);
                     }
                 }
             }

         cairo_push_group(root_instance);
         cairo_set_source_rgb(root_instance, 0, 0, 0);
         cairo_paint(root_instance);
         cairo_set_source_surface(root_instance, surface, 0, 0);
         cairo_paint(root_instance);
         cairo_pop_group_to_source(root_instance); 
cairo_paint(root_instance); 
cairo_surface_flush(cairo_get_target(root_instance));
     }
}

-- 
⚗︎ | /blu.mɛin.dʰak/ | shortens to "Hawk" | he/him/his/himself/Mr.
bluemanedhawk.github.io
Bitches stole my whole ass ␔🭖᷿᪳𝼗᷍⏧𒒫𐻾ࣛ↉�⃣ quoted-printable, can't 
have shit in Thunderbird 😩

Back to comp.graphics.misc | Previous | NextNext in thread | Find similar


Thread

Running into problems while trying to scale Cairo surface to take up maximum space at specific aspect ratio Blue-Maned_Hawk <bluemanedhawk@gmail.com> - 2023-06-11 19:13 -0400
  Re: Running into problems while trying to scale Cairo surface to take up maximum space at specific aspect ratio Ben Bacarisse <ben.usenet@bsb.me.uk> - 2023-06-12 01:07 +0100
    Re: Running into problems while trying to scale Cairo surface to take up maximum space at specific aspect ratio Blue-Maned_Hawk <bluemanedhawk@gmail.com> - 2023-06-11 20:54 -0400
      Re: Running into problems while trying to scale Cairo surface to take up maximum space at specific aspect ratio Ben Bacarisse <ben.usenet@bsb.me.uk> - 2023-06-12 12:24 +0100
        Re: Running into problems while trying to scale Cairo surface to take up maximum space at specific aspect ratio Ben Bacarisse <ben.usenet@bsb.me.uk> - 2023-06-12 14:48 +0100
          Re: Running into problems while trying to scale Cairo surface to take up maximum space at specific aspect ratio Blue-Maned_Hawk <bluemanedhawk@gmail.com> - 2023-06-12 14:23 -0400

csiph-web