diff --git a/CMakeLists.txt b/CMakeLists.txt index 9e1c325..2bc6c58 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -5,7 +5,8 @@ set(CMAKE_EXPORT_COMPILE_COMMANDS ON) find_package(PkgConfig REQUIRED) pkg_check_modules(GTK4 REQUIRED IMPORTED_TARGET gtk4) +pkg_check_modules(LIBRSVG REQUIRED IMPORTED_TARGET librsvg-2.0) add_executable(${PROJECT_NAME} ${SOURCES}) set_property(TARGET ${PROJECT_NAME} PROPERTY C_STANDARD 99) -target_link_libraries(${PROJECT_NAME} PRIVATE PkgConfig::GTK4) +target_link_libraries(${PROJECT_NAME} PRIVATE PkgConfig::GTK4 PkgConfig::LIBRSVG) diff --git a/src/main.c b/src/main.c index c33ee87..3809b04 100644 --- a/src/main.c +++ b/src/main.c @@ -1,31 +1,100 @@ #include #include -#include +#include +#include +#include +#include + +#define BOARD_SIZE 8 +#define LENGTH(array) (sizeof array / sizeof *array) + +enum pieces { + KING, + QUEEN, + ROOK, + BISHOP, + KNIGHT, + PAWN +}; + +enum playerColor { + BLACK, + WHITE +}; + +#define WHITE_PIECE 8 + +typedef uint_least8_t piece_t; + +struct drawData_t { + RsvgHandle **piecesSvg; + piece_t *chessboard; +}; static void draw_event(GtkDrawingArea *area, cairo_t *cr, int width, int height, gpointer data) { - const double fieldSize = (double)(width < height ? width : height) / 8; - const double xOffset = (width - fieldSize * 8) / 2; - const double yOffset = (height - fieldSize * 8) / 2; + const double fieldSize = (double)(width < height ? width : height) / BOARD_SIZE; + const double xOffset = (width - fieldSize * BOARD_SIZE) / 2; + const double yOffset = (height - fieldSize * BOARD_SIZE) / 2; + const struct drawData_t drawData = *(struct drawData_t*)data; + const piece_t *chessboard = drawData.chessboard; + RsvgHandle **piecesSvg = drawData.piecesSvg; for(int x = 0; x < 8; ++x) { for(int y = 0; y < 8; ++y) { cairo_rectangle(cr, xOffset + x * fieldSize, yOffset + y * fieldSize, fieldSize, fieldSize); if((x + y) & 1) cairo_set_source_rgb(cr, 0.46274, 0.5882, 0.3373); else cairo_set_source_rgb(cr, 0.9333, 0.9333, 0.8235); cairo_fill(cr); + const RsvgRectangle rect = {xOffset + x * fieldSize, yOffset + y * fieldSize, fieldSize, fieldSize}; + rsvg_handle_render_document(piecesSvg[0], cr, &rect, NULL); } } } -static void app_activate(GApplication *app, gpointer user_data) { - GtkWindow *win; - GtkWidget *drawArea; +static void on_click(GtkGestureClick *gesture, int n_press, double x, double y, gpointer data) { + g_print("Mouse clicked at (%f, %f)\n", x, y); +} - win = GTK_WINDOW(gtk_window_new()); - drawArea = gtk_drawing_area_new(); - gtk_window_set_child(win, drawArea); - gtk_drawing_area_set_draw_func(GTK_DRAWING_AREA(drawArea), draw_event, NULL, NULL); - gtk_window_set_application(win, GTK_APPLICATION(app)); - gtk_window_present(win); +static void app_activate(GApplication *app, gpointer data) { + GtkWindow *window = GTK_WINDOW(gtk_window_new()); + static RsvgHandle *piecesSvg[16]; + static piece_t chessboard[BOARD_SIZE * BOARD_SIZE]; + static struct drawData_t drawData = {piecesSvg, chessboard}; + { + GtkWidget *drawArea = gtk_drawing_area_new(); + gtk_window_set_child(window, drawArea); + gtk_drawing_area_set_draw_func(GTK_DRAWING_AREA(drawArea), draw_event, &drawData, NULL); + } + { + GtkGesture *gesture = gtk_gesture_click_new(); + g_signal_connect(gesture, "pressed", G_CALLBACK(on_click), NULL); + gtk_widget_add_controller(GTK_WIDGET(window), GTK_EVENT_CONTROLLER(gesture)); + } + { + const char *const piecesFilenames[] = { + "king", + "queen", + "rook", + "bishop", + "knight", + "pawn" + }; + for(uint i = 0; i < LENGTH(piecesFilenames); ++i) { + const char *const color[] = {"black", "white"}; + for(uint j = 0; j < LENGTH(color); ++j) { + char filename[25]; + GError *error = NULL; + sprintf(filename, "pieces/%s_%s.svg", color[j], piecesFilenames[i]); + piecesSvg[i | j ? WHITE_PIECE : 0] = rsvg_handle_new_from_file(filename, &error); + if(error != NULL) { + perror(error->message); + g_clear_error(&error); + exit(1); + } + } + } + } + gtk_window_set_application(window, GTK_APPLICATION(app)); + gtk_window_present(window); } int main(int argc, char **argv) {