Cairo - Auf Surface zeichnen
-
Hallo,
ich möchte gerne ein neues Surface aus einer .png-Datei erstellen und dieses dann einer Struktur zuweisen. Später soll dieses dann gezeichnet werden.
Ich gehe dabei folgendermaßen vor:cairo_surface_t *surf = cairo_image_surface_create_from_png(str); free(str); cairo_t *cr = cairo_create(surf); cairo_scale(cr,1.0/IMAGE_SIZE*size,1.0/IMAGE_SIZE*size); cairo_set_source_surface(cr,surf,0,0); cairo_paint(cr); pieces[i].surface = surf;
Das Problem ist nun, dass Bilder verschiedener Skalierungsstufen übereinander gemalt erscheinen.
Woran könnte das liegen?
Vielen Dank!!
-
Hallo,
ich habe aus meinem Projekt heraus ein kleines compilierbares Beispiel extrahiert, das den Fehler zeigt.
main.h:
#ifndef MAIN_H #define MAIN_H #include <stdlib.h> #include <stdio.h> #include <sys/stat.h> #include <sys/types.h> #include <sys/socket.h> #include <netdb.h> #include <errno.h> #include <netinet/in.h> #include <string.h> #include <unistd.h> #include <pthread.h> #include <gtk/gtk.h> #include <cairo.h> static GtkWidget *mainWindow; static GtkWidget *drawArea; static cairo_surface_t *bauerW; static void frame_callback(GtkWindow *, GdkEvent *, gpointer); static int width = 600, height = 600; static GtkWidget *table; #endif
main.c:
#include "main.h" int squareSize; int IMAGE_SIZE = 250; static void do_drawing(cairo_t *cr) { if(cr == NULL) return; int min = width; if(height < width) min = height; squareSize = min/8; for(int j=0;j<8;j++) { for(int i=0;i<8;i++) { if((i+j)%2 == 0) { cairo_set_source_rgba(cr,.7,.6,.5,1); } else { cairo_set_source_rgba(cr,0.55,0.45,0.35,1); } cairo_rectangle(cr, squareSize*i, squareSize*(j), squareSize, squareSize); cairo_set_line_width(cr, 14); cairo_fill(cr); } } cairo_translate(cr,200,200); cairo_set_source_surface(cr,bauerW,0,0); cairo_paint(cr); } static void scaleImage(int size) { cairo_surface_t *surf = cairo_image_surface_create_from_png("whitePawn.png"); cairo_t *cr = cairo_create(surf); cairo_scale(cr,1.0/IMAGE_SIZE*size,1.0/IMAGE_SIZE*size); cairo_set_source_surface(cr,surf,0,0); cairo_paint(cr); bauerW = surf; } static gboolean on_draw_event(GtkWidget *widget, cairo_t *cr, gpointer user_data) { do_drawing(cr); return FALSE; } int main(int argc, char **argv) { gtk_init(&argc,&argv); bauerW = cairo_image_surface_create_from_png("whitePawn.png"); drawArea = gtk_drawing_area_new(); gtk_widget_set_size_request(drawArea,400,400); gtk_widget_set_events (drawArea, gtk_widget_get_events (drawArea) | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK | GDK_POINTER_MOTION_MASK); g_signal_connect(G_OBJECT(drawArea), "draw",G_CALLBACK(on_draw_event), NULL); mainWindow = gtk_window_new(GTK_WINDOW_TOPLEVEL); gtk_window_set_default_size(GTK_WINDOW(mainWindow),width,height); gtk_widget_add_events(GTK_WIDGET(mainWindow), GDK_CONFIGURE); table = gtk_grid_new(); gtk_grid_attach(GTK_GRID(table),drawArea,0,0,4,4); gtk_container_add(GTK_CONTAINER(mainWindow),table); gtk_widget_add_events(GTK_WIDGET(mainWindow), GDK_CONFIGURE); g_signal_connect(mainWindow,"destroy",G_CALLBACK(gtk_main_quit),NULL); g_signal_connect(G_OBJECT(drawArea), "configure-event",G_CALLBACK(frame_callback), NULL); gtk_widget_set_hexpand(drawArea,TRUE); gtk_widget_set_vexpand(drawArea,TRUE); gtk_widget_set_hexpand(table,TRUE); gtk_widget_set_vexpand(table,TRUE); gtk_widget_show(drawArea); gtk_widget_show(table); gtk_widget_show(mainWindow); gtk_main(); return 0; } void frame_callback(GtkWindow *w, GdkEvent *event, gpointer data) { width = event->configure.width; height = event->configure.height; scaleImage(width/8); }
Als Ergebnis erhalte ich einen weißen Bauern, der in verschiedenen Skalierungsstufen dargestellt wird.
Ich bitte um Denkanstöße :).
-
Naja, Du bemalst die Drawingarea ja auch zweimal mit dem Surface:
das erste mal in frame_callback -> scaleImage(width/8); (configure-event)
das zweite mal in on_draw_event -> do_drawing(cr); (draw)
-
Ich hab's endlich geschafft :).
static void scaleImage(int size) { cairo_surface_t *neu = cairo_image_surface_create(CAIRO_FORMAT_ARGB32,size,size); cairo_surface_t *surf = cairo_image_surface_create_from_png("whitePawn.png"); cairo_t *cr = cairo_create(neu); cairo_scale(cr,1.0/IMAGE_SIZE*size,1.0/IMAGE_SIZE*size); cairo_set_source_surface(cr,surf,0,0); cairo_paint(cr); bauerW = neu; }