Blue-Maned_Hawk
2023-06-11 23:13:50 UTC
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-printa
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-printa