Skip to content

Instantly share code, notes, and snippets.

@rjopek
Created February 18, 2022 00:53
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save rjopek/971b0b87a9dfd6950df133e3567da40b to your computer and use it in GitHub Desktop.
Save rjopek/971b0b87a9dfd6950df133e3567da40b to your computer and use it in GitHub Desktop.
How to correctly implement an image using GLFW and Cairo
/*
*
*/
#include <math.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <cairo/cairo.h>
#include <cairo/cairo-xlib.h>
#include <GLFW/glfw3.h>
#define GLFW_EXPOSE_NATIVE_X11
#include <GLFW/glfw3native.h>
#define UNUSED( x ) ( ( void )( x ) )
typedef struct
{
GLFWwindow * win;
int width;
int height;
Display * xdpy;
Window xwin;
Visual * vis;
cairo_surface_t * surface;
cairo_t * cr;
cairo_surface_t * image;
} GLFW_Cairo;
static GLFW_Cairo gl;
static void key_callback( GLFWwindow * window, int key, int scancode, int action, int mods );
int main()
{
memset( &gl, 0, sizeof( gl ) );
int width = 0, height = 0;
int w, h;
if( ! glfwInit() )
{
glfwTerminate();
exit( EXIT_FAILURE );
}
glfwWindowHint( GLFW_CLIENT_API, GLFW_NO_API );
gl.win = glfwCreateWindow( 720, 512, "GLFW .AND. Cairo", NULL, NULL );
if( ! gl.win )
{
glfwTerminate();
exit( EXIT_FAILURE );
}
glfwSwapInterval( 1 );
gl.xdpy = glfwGetX11Display();
gl.xwin = glfwGetX11Window( gl.win );
gl.vis = DefaultVisual( gl.xdpy, DefaultScreen( gl.xdpy ) );
if( ! gl.vis )
{
glfwTerminate();
exit( EXIT_FAILURE );
}
glfwGetFramebufferSize( gl.win, &gl.width, &gl.height );
gl.surface = cairo_xlib_surface_create( gl.xdpy, gl.xwin, gl.vis, gl.width, gl.height );
gl.cr = cairo_create( gl.surface );
if( ! gl.cr )
{
glfwTerminate();
exit( EXIT_FAILURE );
}
glfwSetKeyCallback( gl.win, key_callback );
while( ! glfwWindowShouldClose( gl.win ) )
{
glfwGetFramebufferSize( gl.win, &gl.width, &gl.height );
cairo_xlib_surface_set_size( gl.surface, gl.width, gl.height );
cairo_push_group( gl.cr );
if( width != gl.width || height != gl.height )
{
cairo_set_source_rgb( gl.cr, 0.0, 0.0, 0.0 );
cairo_set_operator( gl.cr, CAIRO_OPERATOR_SOURCE );
cairo_paint( gl.cr );
//---
gl.image = cairo_image_surface_create_from_png( "cairo.png" );
w = cairo_image_surface_get_width( gl.image );
h = cairo_image_surface_get_height( gl.image );
cairo_scale( gl.cr, 80.0 / w, 80.0 / h );
cairo_set_source_surface( gl.cr, gl.image, 0, 0 );
cairo_paint( gl.cr );
width = gl.width;
height = gl.height;
//---
}
cairo_pop_group_to_source( gl.cr );
cairo_paint( gl.cr );
cairo_surface_flush( gl.surface );
glfwSwapBuffers( gl.win );
glfwPollEvents();
}
cairo_surface_destroy( gl.image );
cairo_destroy( gl.cr );
cairo_surface_finish( gl.surface );
cairo_surface_destroy( gl.surface );
cairo_surface_destroy( gl.image );
glfwDestroyWindow( gl.win );
glfwTerminate();
exit( EXIT_SUCCESS );
}
static void key_callback( GLFWwindow * window, int key, int scancode, int action, int mods )
{
UNUSED( scancode );
UNUSED( mods );
if( action == GLFW_PRESS )
{
return;
}
switch( key )
{
case GLFW_KEY_ESCAPE:
{
glfwSetWindowShouldClose( window, GLFW_TRUE );
break;
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment