Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- /* -*- C++ -*- include/005-drawing ------------------------------------------ */
- #define __included_drawing__
- #ifdef ENABLE_DRAWING
- #include <cairo/cairo-xcb.h>
- #include <cairo/cairo.h>
- #include <xcb/xcb.h>
- #include <xcb/xcb_icccm.h>
- #include <xcb/xcb_image.h>
- #ifdef debug
- #undef debug
- #endif
- #define debug(...) __VA_ARGS__
- namespace {
- namespace draw {
- struct rgba {
- double r;
- double g;
- double b;
- double a;
- };
- struct window {
- size_t width = 0;
- size_t height = 0;
- size_t window_width = 0;
- size_t window_height = 0;
- cairo_surface_t* surface = nullptr;
- cairo_surface_t* image = nullptr;
- cairo_t* cairo = nullptr;
- cairo_t* display = nullptr;
- };
- void rectangle(window& w, point p0, point p1, rgba color) {
- cairo_set_source_rgba(w.cairo, color.r, color.g, color.b, color.a);
- cairo_new_path(w.cairo);
- cairo_rectangle(w.cairo, p0.x, p0.y, p1.x - p0.x, p1.y - p0.y);
- cairo_stroke(w.cairo);
- }
- void square(window& w, point p0, double size, rgba color) {
- cairo_set_source_rgba(w.cairo, color.r, color.g, color.b, color.a);
- cairo_new_path(w.cairo);
- cairo_rectangle(w.cairo, p0.x - size / 2., p0.y - size / 2., size, size);
- cairo_stroke(w.cairo);
- }
- void line(window& w, point p0, point p1, rgba color) {
- cairo_set_source_rgba(w.cairo, color.r, color.g, color.b, color.a);
- cairo_new_path(w.cairo);
- cairo_move_to(w.cairo, p0.x, p0.y);
- cairo_line_to(w.cairo, p1.x, p1.y);
- cairo_stroke(w.cairo);
- }
- void line(window& w, std::vector<point> const& points, rgba color) {
- cairo_set_source_rgba(w.cairo, color.r, color.g, color.b, color.a);
- cairo_new_path(w.cairo);
- cairo_move_to(w.cairo, points[0].x, points[0].y);
- for (auto& point : points)
- cairo_line_to(w.cairo, point.x, point.y);
- cairo_stroke(w.cairo);
- }
- void arrow(window& w, point p0, point p1, rgba color) {
- line(w, p0, p1, color);
- if (p0 == p1)
- return;
- auto dp = normalized(p1 - p0);
- line(w, p1 - dp * 50. + point{static_cast<scalar>(-dp.y), static_cast<scalar>(dp.x)} * 25, p1, color);
- line(w, p1 - dp * 50. - point{static_cast<scalar>(-dp.x), static_cast<scalar>(dp.x)} * 25, p1, color);
- }
- void circle(window& w, point c, double radius, rgba color) {
- cairo_set_source_rgba(w.cairo, color.r, color.g, color.b, color.a);
- cairo_new_path(w.cairo);
- cairo_arc(w.cairo, c.x, c.y, radius, 0.0, M_PI * 2.);
- cairo_stroke(w.cairo);
- }
- template <typename... Ts> inline void join(std::ostream& str, char const* sep, Ts&&... as) {
- auto n = sizeof...(as);
- (int[]){(str << std::forward<Ts>(as) << (--n == 0 ? "" : sep), 0)...};
- }
- template <typename... Ts> inline std::string join(char const* sep, Ts&&... as) {
- auto str = std::stringstream{};
- join(str, sep, std::forward<Ts>(as)...);
- return str.str();
- }
- template <typename... Ts> void text(window& w, point p, rgba color, Ts&&... as) {
- auto text = join(" ", forward<Ts>(as)...);
- cairo_set_source_rgba(w.cairo, color.r, color.g, color.b, color.a);
- cairo_move_to(w.cairo, p.x, p.y);
- cairo_show_text(w.cairo, text.c_str());
- }
- auto xcb = xcb_connect(nullptr, nullptr);
- window init(size_t width, size_t height, size_t window_width = 1280, size_t window_height = 720, std::string const& title = "DEBUG") {
- auto w = window{};
- w.width = width;
- w.height = height;
- w.window_width = window_width;
- w.window_height = window_height;
- assert(xcb);
- assert(!xcb_connection_has_error(xcb));
- auto window = xcb_generate_id(xcb);
- auto screen = xcb_setup_roots_iterator(xcb_get_setup(xcb)).data;
- unsigned params[] = {1, XCB_EVENT_MASK_EXPOSURE};
- xcb_create_window(xcb, XCB_COPY_FROM_PARENT, window, screen->root, 0, 0, w.window_width, w.window_height, 5, XCB_WINDOW_CLASS_INPUT_OUTPUT,
- screen->root_visual, XCB_CW_BACK_PIXEL, params);
- xcb_icccm_set_wm_class(xcb, window, std::strlen("CodinGame"), "CodinGame");
- xcb_icccm_set_wm_name(xcb, window, XCB_ATOM_STRING, 8, title.size(), title.c_str());
- xcb_map_window(xcb, window);
- xcb_flush(xcb);
- for (auto depth_iter = xcb_screen_allowed_depths_iterator(screen); w.surface == nullptr && depth_iter.rem; xcb_depth_next(&depth_iter)) {
- for (auto visual_iter = xcb_depth_visuals_iterator(depth_iter.data); w.surface == nullptr && visual_iter.rem; xcb_visualtype_next(&visual_iter)) {
- if (screen->root_visual != visual_iter.data->visual_id)
- continue;
- w.surface = cairo_xcb_surface_create(xcb, window, visual_iter.data, 1, 1);
- }
- }
- assert(w.surface);
- cairo_xcb_surface_set_size(w.surface, w.window_width, w.window_height);
- xcb_flush(xcb);
- auto const scalex = w.window_width / static_cast<double>(w.width);
- auto const scaley = w.window_height / static_cast<double>(w.height);
- cairo_surface_set_device_scale(w.surface, scalex, scaley);
- w.display = cairo_create(w.surface);
- assert(w.display);
- w.image = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, w.window_width, w.window_height);
- cairo_surface_set_device_scale(w.image, scalex, scaley);
- w.cairo = cairo_create(w.image);
- assert(w.cairo);
- cairo_select_font_face(w.cairo, "DejaVu Sans Mono", CAIRO_FONT_SLANT_NORMAL, CAIRO_FONT_WEIGHT_NORMAL);
- cairo_set_line_width(w.cairo, 1. / max(scalex, scaley));
- cairo_set_font_size(w.cairo, w.width * 0.0078125);
- cairo_set_antialias(w.cairo, CAIRO_ANTIALIAS_SUBPIXEL);
- cairo_set_source_rgba(w.cairo, 0.0, 0.0, 0.0, 1.0);
- cairo_paint(w.cairo);
- xcb_flush(xcb);
- return w;
- }
- void flush(window& w) {
- cairo_set_source_surface(w.display, w.image, 0, 0);
- cairo_paint(w.display);
- cairo_surface_flush(w.surface);
- xcb_flush(xcb);
- }
- void clear(window& w, rgba color = rgba{0.0, 0.0, 0.0, 1.0}) {
- cairo_set_source_rgba(w.cairo, color.r, color.g, color.b, color.a);
- cairo_paint(w.cairo);
- }
- }
- }
- #else
- #define debug(...)
- #endif
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement