I need help about SDL 2 - c

I have a problem when I run my prog : "prog.exe just stopped working".
#include <SDL.h>
#include <stdlib.h>
#include <stdio.h>
int main(int argc, char* argv[])
{
SDL_Surface *screen; // even with SDL2, we can still bring ancient code back
SDL_Window *window;
SDL_Surface *image;
SDL_Init(SDL_INIT_VIDEO); // init video
// create the window like normal
window = SDL_CreateWindow("SDL2 Example", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, 640, 480, 0);
// but instead of creating a renderer, we can draw directly to the screen
screen = SDL_GetWindowSurface(window);
// let's just show some classic code for reference
SDL_FillRect(image, NULL, SDL_MapRGB(image->format, 0, 255, 0));
SDL_BlitSurface(image, NULL, screen, NULL); // blit it to the screen
SDL_FreeSurface(image);
// this works just like SDL_Flip() in SDL 1.2
SDL_UpdateWindowSurface(window);
// show image for 2 seconds
SDL_Delay(2000);
SDL_DestroyWindow(window);
SDL_Quit();
return 0;
}
// gcc src/main.c -o bin/prog -I include -L lib -lmingw32 -lSDL2main -lSDL2

As Eugene Sh. pointed out your surface isn't initialized
You need to create the surface someway, either by loading an IMG or using SDL_CreateRGBSurface. Add this before calling SDL_FillRect and now your code shows a green screen.
image = SDL_CreateRGBSurface(0, width, height, 32, 0, 0, 0, 0);

Related

c printing more pages with cairo and cups

I need, in C in under a linux environment, to print documents with an image as a background.
I found an example which use Cairo vector graphics library to author a PostScript, and then sends it that off to CUPS for printing.
I modified the initial source code to integrate it with a background image (background-img.png) .
The text to be printed is more than one page, I would like to know how can I print on multiple pages keeping the same image as background and changing only the foreground text ?
How can I resize the background image to match the size of an A4 page ?
Here is the code used as a starting point :
// compile with:
// gcc -Wall -o cairo_print_png cairo_print_png.c `pkg-config --cflags --libs cairo` `cups-config --cflags --libs`
#include <stdio.h>
#include <cairo.h>
#include <cairo-ps.h>
#include <cups/cups.h>
// A4 width, height in points, from GhostView manual:
// http://www.gnu.org/software/gv/manual/html_node/Paper-Keywords-and-paper-size-in-points.html
#define WIDTH 595
#define HEIGHT 842
int main(int argc, char** argv) {
int widthPng, heightPng;
if (argc!= 2){
fprintf (stderr, "usage: %s word\n", argv[0]);
return 1;
}
// setup
char* tmpfilename = tempnam(NULL,NULL);
cairo_surface_t* surface = cairo_ps_surface_create(tmpfilename,
WIDTH,
HEIGHT);
cairo_t *context = cairo_create(surface);
// draw some text
cairo_select_font_face(context,
"mono",
CAIRO_FONT_SLANT_NORMAL,
CAIRO_FONT_WEIGHT_NORMAL);
cairo_set_font_size(context, 30);
cairo_move_to(context, WIDTH/2, HEIGHT/2);
cairo_show_text(context, argv[1]); // the text we got as a parameter
// draw a dotted box
const double pattern[] = {15.0, 10.0};
cairo_set_dash(context, pattern, 2, 0);
cairo_set_line_width(context, 5);
cairo_rectangle(context, WIDTH*0.33, HEIGHT*0.33, WIDTH*0.5, WIDTH*0.5);
cairo_stroke(context);
cairo_surface_t* surface_png = cairo_image_surface_create_from_png("background-img.png");
if (surface_png == NULL || cairo_surface_status (surface_png)) {
printf("***** load error *****\n");
}
widthPng = cairo_image_surface_get_width(surface_png);
heightPng = cairo_image_surface_get_height(surface_png);
cairo_surface_set_device_scale (surface_png,
widthPng/WIDTH*1.33,
heightPng/HEIGHT*1.29);
cairo_set_operator(context, CAIRO_OPERATOR_DEST_OVER);
cairo_set_source_surface(context, surface_png, 0, 0);
cairo_paint(context);
/*** second page ***/
{
cairo_t *cr;
cr = cairo_create (surface);
/* Duplicate the last frame onto another page. (This is just a
* way to sneak cairo_copy_page into the test).
*/
cairo_show_page (cr);
//draw text on second page
cairo_select_font_face(cr,
"mono",
CAIRO_FONT_SLANT_NORMAL,
CAIRO_FONT_WEIGHT_NORMAL);
cairo_set_font_size(cr, 30);
cairo_move_to(cr, WIDTH/2, HEIGHT/2);
cairo_show_text(cr, "text over second page");
cairo_set_operator(cr, CAIRO_OPERATOR_DEST_OVER);
cairo_set_source_surface(cr, surface_png, 0, 0);
cairo_paint(cr);
cairo_destroy (cr);
}
// finish up
cairo_show_page(context);
cairo_destroy(context);
cairo_surface_flush(surface);
cairo_surface_destroy(surface);
cairo_surface_flush(surface_png);
cairo_surface_destroy(surface_png);
// print
cupsPrintFile("Cups-PDF", tmpfilename, "cairo PS", 0, NULL);
unlink(tmpfilename);
return 0;
}
Update :
I added the text enclosed in "second page". I can create another page, but I can't resize the background image.
How can I resize the image to fit the A4 size?
Update
I used cairo_surface_set_device_scale to resize the image, and the mono font to use a fixed width font
Update
The problem now is that the code works with cairo-1.15.12-4 while if I try to compile with cairo-1.8.8-3.1 I get undefined reference to cairo_surface_set_device_scale'.
What can I solve the problem? At the moment I cannot update the libraries using rpm as I would have to update the whole operating system.
Can I somehow replace the cairo_surface_set_device_scale with functions that perform the same task?
Update:
In the Cairo Mailing Lists I found the following function that does the job :
cairo_surface_t *scale_to_half(cairo_surface_t *s, int orig_width, int
orig_height, double x_scale, double y_scale)
{
cairo_surface_t *result = cairo_surface_create_similar(s,
cairo_surface_get_content(s), orig_width*x_scale, orig_height*y_scale);
cairo_t *cr = cairo_create(result);
cairo_scale(cr, x_scale, y_scale);
cairo_set_source_surface(cr, s, 0, 0);
cairo_set_operator(cr, CAIRO_OPERATOR_SOURCE);
cairo_paint(cr);
cairo_destroy(cr);
return result;
}
but the quality is very low compared to cairo_surface_set_device_scale.

OpenGL 3.1 with SDL2 context fails to output anything on screen

I am trying to get a simple demo of OpenGL working with SDL2. I am using MacOS Big Sur 11.3.1, my SDL version is 2.0.16, and my attempted OpenGL version is 3.1.
Everything seems to work fine at first, given that SDL is initialized successfully, the SDL window is not null, and the OpenGL context is not null either. But when trying to print out the vendor name, renderer name, and version name of OpenGL, all of the strings are null:
vendor = (null)
renderer = (null)
version = (null)
This also explains why nothing appears on the window. I have followed plenty of tutorials that go over using SDL2 with OpenGL, but none of them have worked for me.
I am compiling like this: clang -O3 -lSDL2 -lGL gl_sdl.c.
If anyone knows what is going on, please let me know; I am very confused. My code is below.
#include <SDL2/SDL.h>
#include <GL/gl.h>
enum {w = 800, h = 600};
#define FAIL(msg) {fprintf(stderr, "Could not " msg "\n"); return 1;}
// https://www.khronos.org/opengl/wiki/Tutorial1:_Creating_a_Cross_Platform_OpenGL_3.2_Context_in_SDL_(C_/_SDL)
// clang -O3 -lSDL2 -lGL gl_sdl.c && ./a.out
int main(void) {
if (SDL_Init(SDL_INIT_VIDEO) < 0) FAIL("initialize SDL");
SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_CORE);
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 3);
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 1);
// Turn on double buffering with a 24bit Z buffer. You may need to change this to 16 or 32 for your system
SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);
SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 24);
SDL_Window* const window = SDL_CreateWindow("gl_sdl", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, w, h, SDL_WINDOW_OPENGL);
if (window == NULL) FAIL("create a window");
SDL_GLContext context = SDL_GL_CreateContext(window);
if (context == NULL) FAIL("create a context");
// This makes our buffer swap syncronized with the monitor's vertical refresh
SDL_GL_SetSwapInterval(1);
printf("vendor = %s\nrenderer = %s\nversion = %s\n", glGetString(GL_VENDOR), glGetString(GL_RENDERER), glGetString(GL_VERSION));
SDL_Event event;
while (1) {
while (SDL_PollEvent(&event)) {
if (event.type == SDL_QUIT) {
SDL_GL_DeleteContext(context);
SDL_DestroyWindow(window);
SDL_Quit();
return 0;
}
}
// Blue
glClearColor(0.0f, 0.0f, 1.0f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT);
SDL_GL_SwapWindow(window);
SDL_Delay(20);
}
}
MacOS uses a different library flag for OpenGL than Linux and Windows. Instead of -lGL, use -framework OpenGL. E.g.
clang -O3 gl_sdl.c -lSDL2 -framework OpenGL
On a side note, the program requests a context for OpenGL 3.1, but does not use an OpenGL Loading Library (or loads any functions manually). As is, this happens to cause no problems, only because no functions from OpenGL >1.1 are used.

How to make the SDL_ttf work with the SDL2?

I've recently switch from SDL 1.0 to 2.0 for some program necessity. I've successfully managed to make it work as well as SDL_image that I use. However, for some reason, SDL_ttf 2.0 does not work on my program. I have paid attention to use the function of the 2.0 and not the 1.0 and tested the ttf with programs that weren't my owns, nothing worked. Usually, the program runs until it has to print text then it closes and send "process returned -1073741819" which is for what I know an error message in a program for it should return 0. I tried both x64 and x86 but none worked though the x86 seemed to give better results.
#include <stdlib.h>
#include <stdio.h>
#include <SDL2/SDL.h>
#include <SDL2/SDL_image.h>
#include <SDL2/SDL_ttf.h>
int main()
{
SDL_Surface *logo = NULL, *Wreed, *Reminder, *ecran = NULL;
SDL_Window *window = NULL;
SDL_Texture *textureLogo = NULL, *textureWreed = NULL, *textureReminder = NULL;
SDL_Rect positionLogo = {1100/2 - 600/2, 700/2 - 600/2, 600, 600}, /*positionWreed,*/ positionReminder;
TTF_Font *police = NULL;
SDL_Color couleur = {0,0,0};
SDL_Renderer* renderer;
police = TTF_OpenFont("arial.ttf", 40);
window = SDL_CreateWindow("Wreed Reminder", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, 1100, 700, SDL_WINDOW_OPENGL);
renderer = SDL_CreateRenderer(window, -1, SDL_RENDERER_ACCELERATED);
SDL_SetRenderDrawColor(renderer, 255, 255, 255, 255);
ecran = SDL_GetWindowSurface(window);
SDL_RenderClear(renderer);
Wreed = TTF_RenderText_Blended(police, "Wreed", couleur);
textureWreed = SDL_CreateTextureFromSurface(renderer, Wreed);
SDL_Rect positionWreed = {10, 10, 10, 10};
SDL_RenderCopy(renderer, textureWreed, NULL, &positionWreed);
SDL_RenderPresent(renderer);
SDL_Delay(5000);
}
If anyone knows how to fix this, please help.
Well, I don't know quite what happened but I reinstalled the latest version of the ttf and set the x86 but it didn't work, so I tried x64, just in case. Didn't work either. Then, I reset the x86 and, surprise, it is working.

How do I separate window creation and a draw function in C using SDL2?

I am trying to separate drawing (drawing.c) to the screen from the creation of a window and renderer (initialize.c). I want them both in different source-files. The drawing code runs and is executed, but the graphics are not updated.
If I put the code from the drawing file inside the create window and rendering file, it works. The color in the window is now red.
main.c - The main file
SDL_Window *window;
SDL_Renderer *renderer;
int main()
{
initialize(window, renderer);
draw(renderer);
SDL_Dealy(5000);
SDL_Quit();
}
initialize.c - Create window and renderer
void initialize(SDL_Window *window, SDL_Renderer *renderer)
{
SDL_Init(SDL_INIT_VIDEO);
window = SDL_CreateWindow("Title",
SDL_WINDOWPOS_UNDEFINED,
SDL_WINDOWPOS_UNDEFINED,
640, 480, 0);
renderer = SDL_CreateRenderer(window, -1, 0);
}
draw.c - Draw graphics to window
void draw(SDL_Renderer *renderer)
{
SDL_SetRenderDrawColor(renderer, 255, 0, 0, 255);
SDL_RenderClear(renderer);
SDL_RenderPresent(renderer);
}
When I run the code the window display is black. It is supposed to be filled with red. I get no error messages when I run the code. The new color graphics are never rendered visible.
I can't see how it could have worked in single file unless actual code is different from presented in question. Look at your initialise function:
void initialize(SDL_Window *window, SDL_Renderer *renderer)
{
SDL_Init(SDL_INIT_VIDEO);
window = SDL_CreateWindow("Title",
SDL_WINDOWPOS_UNDEFINED,
SDL_WINDOWPOS_UNDEFINED,
640, 480, 0);
renderer = SDL_CreateRenderer(window, -1, 0);
}
When you call it from main as initialize(window, renderer);, it gets values of global window and renderer. Then it assigns new window/renderer to its local variables, which gets lost when function returns - no global variable is modified after this. Then you call draw(renderer); with the same global not-assigned renderer (NULL) - no way it would work as you expect.
Basically function can't modify anything passed as its arguments because it gets copy of passed values. Correct version would look like this:
void initialize(SDL_Window **window, SDL_Renderer **renderer)
{
SDL_Init(SDL_INIT_WINDOW);
*window = SDL_CreateWindow("Title", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, 640, 480, 0);
*renderer = SDL_CreateRenderer(window, -1, 0);
}
// ...
// in file with main func
SDL_Window *window;
SDL_Renderer *renderer;
void initialize(SDL_Window **window, SDL_Renderer **renderer);
void draw(SDL_Renderer *renderer);
int main()
{
// ...
initialize(&window, &renderer);
draw(renderer);
// ...
}
This is the same way how SDL_CreateWindowAndRenderer operates.
Another thing is that you can't expect draw-and-delay to be correctly displayed; it may work on your configuration of OS/window manager/settings/luck but not others. Refresh loop is essential.

Make writing and lines appear on a GTK Window ... XLIB and GDK used

What my code (below) does:
Creates a XLIB window with a background color
Draws a string on the window
Draws a line on the window
Creates a GTK+ window
Makes the GTK+ window realise the XLIB window exsists via a GDK window
Display the output of the XLIB window inside the GTK+ window
It works and creates a window of the correct colour but it doesn't draw the string or the line on the screen. Any ideas of how to make it appear or where im going wrong?
The reason I am not using the GTK+ drawing functions is because this a test program in reality all the drawing needs to come from the xlib window.
#include <gtk/gtk.h>
#include <gdk/gdkx.h>
#include <X11/Xlib.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
static void destroy(GtkWidget *widget, gpointer data ) {
gtk_main_quit ();
}
int main(int argc, char** argv) {
GtkWidget *xwindow;
//Open the display
Display *display = XOpenDisplay(NULL);
int screen = DefaultScreen(display);
//Create the window
Window w = XCreateSimpleWindow(display, DefaultRootWindow(display), 0, 0,
200, 100, 20, black, 10201020);
XSelectInput(display, w, StructureNotifyMask);
XMapWindow(display, w);
GC gc = XCreateGC(display, w, 0, NULL);
for(;;) {
XEvent e;
XNextEvent(display, &e);
if (e.type == MapNotify)
break;
}
XDrawString(display, w, gc, 10, 10, "HelloWorld!", 12);
XDrawLine(display, w, gc, 10, 60, 180, 20);
XFlush(display);
//SET UP
gtk_init (&argc, &argv);
//xwindow
xwindow = gtk_window_new(GTK_WINDOW_TOPLEVEL);
g_signal_connect (xwindow, "destroy",
G_CALLBACK (destroy), NULL);
g_signal_connect (xwindow, "destroy",
G_CALLBACK (print), NULL);
gtk_widget_realize(xwindow);
xwindow->window = gdk_window_foreign_new((guint32)w);
//SET UP
gtk_widget_show(xwindow);
gtk_main ();
return 0;
}
I believe this is simply due to a misunderstanding of what "drawing" really means, here.
The Xlib drawing model isn't "state-ful", it won't remember that your particular window has had some text drawn in a particular location, and then a line, and so on. The drawing happens immediately when you request it, and is then considered "done", i.e. forgotten about at the protocol level.
When you wrap the X window in a GTK+ widget, it will likely cause the X window system to attempt to refresh the contents of the X window, but that doesn't do anything, which is why your initial graphics are lost.
In short, you need to be able to respond to requests to redraw the window as needed.

Resources