use cairo instead of GdkPixmap / gdk_draw_*

This commit is contained in:
wdlkmpx 2021-01-19 15:11:02 +08:00
parent 79657f6ccb
commit f912ea7a28
3 changed files with 58 additions and 48 deletions

View File

@ -19,8 +19,6 @@
#include "mainwin.h" #include "mainwin.h"
#include "game.h" #include "game.h"
GdkPixmap *_pixmap = NULL;
/* x and y of cell "under pointer" */ /* x and y of cell "under pointer" */
gint _pointer_x = 0, _pointer_y = 0; gint _pointer_x = 0, _pointer_y = 0;
@ -38,6 +36,7 @@ volatile gint _phase = 0;
/* jumping animation timer tag */ /* jumping animation timer tag */
guint _timer_tag = 0; guint _timer_tag = 0;
gboolean have_path(gint source_ball, gint target_ball); gboolean have_path(gint source_ball, gint target_ball);
void move_ball(gint source_ball, gint target_ball); void move_ball(gint source_ball, gint target_ball);
@ -64,27 +63,20 @@ gint get_destroy_phase(gint x, gint y) {
return board_get_destroy_at_xy(x, y); return board_get_destroy_at_xy(x, y);
} }
void update_rectangle(gint x, gint y, gint w, gint h) { static void update_rectangle (gint x, gint y, gint w, gint h)
GtkWidget *widget = mw_get_da(); {
GtkWidget * board_w = mw_get_da();
if (!widget || !_pixmap) { gtk_widget_queue_draw_area (board_w, x, y, w, h);
return;
}
gdk_draw_drawable (gtk_widget_get_window (widget),
widget->style->fg_gc[gtk_widget_get_state(widget)],
_pixmap, x, y, x, y, w, h);
} }
void draw_ball_no_update(gint ballcolor, gint x, gint y, gint jumpnum, gint destroynum) void draw_ball_no_update(gint ballcolor, gint x, gint y, gint jumpnum, gint destroynum)
{ {
GtkWidget *widget = mw_get_da();
GdkGC *gc = widget->style->fg_gc[gtk_widget_get_state(widget)];
gint cxs = gtkbTheme->emptycell.xsize; gint cxs = gtkbTheme->emptycell.xsize;
gint cys = gtkbTheme->emptycell.ysize; gint cys = gtkbTheme->emptycell.ysize;
GtkbPixmap *obj; GtkbPixmap *obj;
gint xr, yr; gint xr, yr;
if (!widget || !_pixmap) { if (!pixsurf) {
return; return;
} }
@ -93,13 +85,12 @@ void draw_ball_no_update(gint ballcolor, gint x, gint y, gint jumpnum, gint dest
} else { } else {
obj = &gtkbTheme->emptycell; obj = &gtkbTheme->emptycell;
} }
gdk_draw_pixbuf (_pixmap,
gc, cairo_t * cr = cairo_create (pixsurf);
obj->pixbuf, gdk_cairo_set_source_pixbuf (cr, obj->pixbuf, x * cxs, y * cys);
0, 0, cairo_rectangle (cr, x * cxs, y * cys, cxs, cys);
x * cxs, y * cys, cairo_fill (cr);
cxs, cys,
GDK_RGB_DITHER_NONE, 0, 0);
if (ballcolor > 0) { /* ball */ if (ballcolor > 0) { /* ball */
if (!jumpnum && !destroynum) { /* still ball */ if (!jumpnum && !destroynum) { /* still ball */
@ -117,13 +108,10 @@ void draw_ball_no_update(gint ballcolor, gint x, gint y, gint jumpnum, gint dest
xr = x * cxs + (cxs - obj->xsize) / 2; xr = x * cxs + (cxs - obj->xsize) / 2;
yr = y * cys + (cys - obj->ysize) / 2; yr = y * cys + (cys - obj->ysize) / 2;
gdk_draw_pixbuf (_pixmap,
gc, gdk_cairo_set_source_pixbuf (cr, obj->pixbuf, xr, yr);
obj->pixbuf, cairo_paint (cr);
0, 0, cairo_destroy (cr);
xr, yr,
obj->xsize, obj->ysize,
GDK_RGB_DITHER_NONE, 0, 0);
} }
void draw_ball(gint ballcolor, gint x, gint y, gint jumpnum, gint destroynum) { void draw_ball(gint ballcolor, gint x, gint y, gint jumpnum, gint destroynum) {
@ -147,8 +135,9 @@ void redraw_pointer(void) {
void draw_board(void) { void draw_board(void) {
gint i, j; gint i, j;
GtkWidget * board_w = mw_get_da();
if (!mw_get_da()) { if (!board_w) {
return; return;
} }
for (j = 0; j < rules_get_height(); j++) { for (j = 0; j < rules_get_height(); j++) {
@ -158,7 +147,8 @@ void draw_board(void) {
} }
} }
} }
update_rectangle(0, 0, -1, -1);
gtk_widget_queue_draw (board_w);
} }
gint inc_with_limit(gint val, gint lim) { gint inc_with_limit(gint val, gint lim) {
@ -342,10 +332,17 @@ void remake_board(gint numoldchilds, gboolean isnextvalid) {
cxs = gtkbTheme->emptycell.xsize; cxs = gtkbTheme->emptycell.xsize;
cys = gtkbTheme->emptycell.ysize; cys = gtkbTheme->emptycell.ysize;
gtk_widget_set_size_request(mw_get_da(), rules_get_width() * cxs, rules_get_height() * cys); gtk_widget_set_size_request(mw_get_da(), rules_get_width() * cxs, rules_get_height() * cys);
if (_pixmap) { if (pixsurf) {
g_object_unref(_pixmap); g_object_unref(pixsurf);
} }
_pixmap = gdk_pixmap_new(mw_get_da()->window, rules_get_width() * cxs, rules_get_height() * cys, -1);
if (pixsurf) {
cairo_surface_destroy (pixsurf);
}
pixsurf = gdk_window_create_similar_surface (gtk_widget_get_window (mw_get_da()),
CAIRO_CONTENT_COLOR_ALPHA,
rules_get_width() * cxs, rules_get_height() * cys);
draw_board(); draw_board();
} }
@ -358,22 +355,25 @@ void draw_next_balls(void) {
} }
/* Refill the screen from the backing pixmap */ /* Refill the screen from the backing pixmap */
gint expose_event(GtkWidget *widget, GdkEventExpose *event) { gint expose_event (GtkWidget *widget, GdkEventExpose *event)
GdkRectangle *rects; {
int n_rects; cairo_t * cr = gdk_cairo_create (gtk_widget_get_window (widget));
int i; GdkRectangle * area = &(event->area);
gdk_region_get_rectangles(event->region, &rects, &n_rects); GtkAllocation a;
gtk_widget_get_allocation (widget, &a);
for (i = 0; i < n_rects; i++) { if (area->width == a.width) {
gdk_draw_drawable (gtk_widget_get_window (widget), cairo_set_source_surface (cr, pixsurf, 0, 0);
widget->style->fg_gc[gtk_widget_get_state(widget)], cairo_paint (cr);
_pixmap, rects[i].x, rects[i].y, rects[i].x, rects[i].y, } else {
rects[i].width, rects[i].height); //cairo_save (cr);
cairo_translate (cr, area->x, area->y);
cairo_set_source_surface (cr, pixsurf, -area->x, -area->y);
cairo_rectangle (cr, 0, 0, area->width, area->height);
cairo_fill (cr);
//cairo_restore (cr);
} }
cairo_destroy (cr);
g_free (rects);
return FALSE; return FALSE;
} }

View File

@ -25,13 +25,17 @@ GtkWidget *_user_score_label = NULL;
/* box for next balls */ /* box for next balls */
GtkWidget *_small_balls_box; GtkWidget *_small_balls_box;
/* Backing pixmap for drawing area */ /* board */
GtkWidget *_drawing_area = NULL; GtkWidget *_drawing_area = NULL;
GtkWidget *mw_get_da(void) { GtkWidget *mw_get_da(void) {
return _drawing_area; return _drawing_area;
} }
/* Backing pixmap for drawing area */
cairo_surface_t * pixsurf = NULL;
/* add child widget to "next balls" display area */ /* add child widget to "next balls" display area */
void mw_small_balls_add(GtkWidget *child) { void mw_small_balls_add(GtkWidget *child) {
gtk_box_pack_start(GTK_BOX(_small_balls_box), child, FALSE, FALSE, 0); gtk_box_pack_start(GTK_BOX(_small_balls_box), child, FALSE, FALSE, 0);
@ -142,6 +146,10 @@ gint _user_action_event(GtkWidget *w, GdkEvent *ev)
static void main_window_destroy_cb (GtkWidget * w, gpointer user_data) static void main_window_destroy_cb (GtkWidget * w, gpointer user_data)
{ {
if (pixsurf) {
cairo_surface_destroy (pixsurf);
pixsurf = NULL;
}
gtkb_theme_free_handler (NULL, NULL); gtkb_theme_free_handler (NULL, NULL);
gtk_main_quit (); gtk_main_quit ();
} }

View File

@ -1,6 +1,8 @@
#ifndef __MAINWIN_H__ #ifndef __MAINWIN_H__
#define __MAINWIN_H__ #define __MAINWIN_H__
cairo_surface_t * pixsurf;
void mw_create(gint da_width, gint da_height); void mw_create(gint da_width, gint da_height);
void mw_small_balls_add(GtkWidget *child); void mw_small_balls_add(GtkWidget *child);
void mw_show_hide_next_balls(gboolean show); void mw_show_hide_next_balls(gboolean show);