Advertisement
Guest User

Untitled

a guest
Aug 21st, 2016
230
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 5.86 KB | None | 0 0
  1. /* -*- C++ -*- include/005-drawing ------------------------------------------ */
  2. #define __included_drawing__
  3.  
  4. #ifdef ENABLE_DRAWING
  5. #include <cairo/cairo-xcb.h>
  6. #include <cairo/cairo.h>
  7. #include <xcb/xcb.h>
  8. #include <xcb/xcb_icccm.h>
  9. #include <xcb/xcb_image.h>
  10.  
  11. #ifdef debug
  12. #undef debug
  13. #endif
  14.  
  15. #define debug(...) __VA_ARGS__
  16.  
  17. namespace {
  18. namespace draw {
  19. struct rgba {
  20. double r;
  21. double g;
  22. double b;
  23. double a;
  24. };
  25.  
  26. struct window {
  27. size_t width = 0;
  28. size_t height = 0;
  29. size_t window_width = 0;
  30. size_t window_height = 0;
  31.  
  32. cairo_surface_t* surface = nullptr;
  33. cairo_surface_t* image = nullptr;
  34. cairo_t* cairo = nullptr;
  35. cairo_t* display = nullptr;
  36. };
  37.  
  38. void rectangle(window& w, point p0, point p1, rgba color) {
  39. cairo_set_source_rgba(w.cairo, color.r, color.g, color.b, color.a);
  40. cairo_new_path(w.cairo);
  41. cairo_rectangle(w.cairo, p0.x, p0.y, p1.x - p0.x, p1.y - p0.y);
  42. cairo_stroke(w.cairo);
  43. }
  44.  
  45. void square(window& w, point p0, double size, rgba color) {
  46. cairo_set_source_rgba(w.cairo, color.r, color.g, color.b, color.a);
  47. cairo_new_path(w.cairo);
  48. cairo_rectangle(w.cairo, p0.x - size / 2., p0.y - size / 2., size, size);
  49. cairo_stroke(w.cairo);
  50. }
  51.  
  52. void line(window& w, point p0, point p1, rgba color) {
  53. cairo_set_source_rgba(w.cairo, color.r, color.g, color.b, color.a);
  54. cairo_new_path(w.cairo);
  55. cairo_move_to(w.cairo, p0.x, p0.y);
  56. cairo_line_to(w.cairo, p1.x, p1.y);
  57. cairo_stroke(w.cairo);
  58. }
  59.  
  60. void line(window& w, std::vector<point> const& points, rgba color) {
  61. cairo_set_source_rgba(w.cairo, color.r, color.g, color.b, color.a);
  62. cairo_new_path(w.cairo);
  63. cairo_move_to(w.cairo, points[0].x, points[0].y);
  64. for (auto& point : points)
  65. cairo_line_to(w.cairo, point.x, point.y);
  66. cairo_stroke(w.cairo);
  67. }
  68.  
  69. void arrow(window& w, point p0, point p1, rgba color) {
  70. line(w, p0, p1, color);
  71. if (p0 == p1)
  72. return;
  73.  
  74. auto dp = normalized(p1 - p0);
  75. line(w, p1 - dp * 50. + point{static_cast<scalar>(-dp.y), static_cast<scalar>(dp.x)} * 25, p1, color);
  76. line(w, p1 - dp * 50. - point{static_cast<scalar>(-dp.x), static_cast<scalar>(dp.x)} * 25, p1, color);
  77. }
  78.  
  79. void circle(window& w, point c, double radius, rgba color) {
  80. cairo_set_source_rgba(w.cairo, color.r, color.g, color.b, color.a);
  81. cairo_new_path(w.cairo);
  82. cairo_arc(w.cairo, c.x, c.y, radius, 0.0, M_PI * 2.);
  83. cairo_stroke(w.cairo);
  84. }
  85.  
  86. template <typename... Ts> inline void join(std::ostream& str, char const* sep, Ts&&... as) {
  87. auto n = sizeof...(as);
  88. (int[]){(str << std::forward<Ts>(as) << (--n == 0 ? "" : sep), 0)...};
  89. }
  90. template <typename... Ts> inline std::string join(char const* sep, Ts&&... as) {
  91. auto str = std::stringstream{};
  92. join(str, sep, std::forward<Ts>(as)...);
  93. return str.str();
  94. }
  95.  
  96. template <typename... Ts> void text(window& w, point p, rgba color, Ts&&... as) {
  97. auto text = join(" ", forward<Ts>(as)...);
  98. cairo_set_source_rgba(w.cairo, color.r, color.g, color.b, color.a);
  99. cairo_move_to(w.cairo, p.x, p.y);
  100. cairo_show_text(w.cairo, text.c_str());
  101. }
  102.  
  103. auto xcb = xcb_connect(nullptr, nullptr);
  104.  
  105. window init(size_t width, size_t height, size_t window_width = 1280, size_t window_height = 720, std::string const& title = "DEBUG") {
  106. auto w = window{};
  107. w.width = width;
  108. w.height = height;
  109. w.window_width = window_width;
  110. w.window_height = window_height;
  111.  
  112. assert(xcb);
  113. assert(!xcb_connection_has_error(xcb));
  114.  
  115. auto window = xcb_generate_id(xcb);
  116. auto screen = xcb_setup_roots_iterator(xcb_get_setup(xcb)).data;
  117.  
  118. unsigned params[] = {1, XCB_EVENT_MASK_EXPOSURE};
  119. 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,
  120. screen->root_visual, XCB_CW_BACK_PIXEL, params);
  121. xcb_icccm_set_wm_class(xcb, window, std::strlen("CodinGame"), "CodinGame");
  122. xcb_icccm_set_wm_name(xcb, window, XCB_ATOM_STRING, 8, title.size(), title.c_str());
  123. xcb_map_window(xcb, window);
  124. xcb_flush(xcb);
  125.  
  126. for (auto depth_iter = xcb_screen_allowed_depths_iterator(screen); w.surface == nullptr && depth_iter.rem; xcb_depth_next(&depth_iter)) {
  127. for (auto visual_iter = xcb_depth_visuals_iterator(depth_iter.data); w.surface == nullptr && visual_iter.rem; xcb_visualtype_next(&visual_iter)) {
  128. if (screen->root_visual != visual_iter.data->visual_id)
  129. continue;
  130.  
  131. w.surface = cairo_xcb_surface_create(xcb, window, visual_iter.data, 1, 1);
  132. }
  133. }
  134. assert(w.surface);
  135. cairo_xcb_surface_set_size(w.surface, w.window_width, w.window_height);
  136. xcb_flush(xcb);
  137.  
  138. auto const scalex = w.window_width / static_cast<double>(w.width);
  139. auto const scaley = w.window_height / static_cast<double>(w.height);
  140. cairo_surface_set_device_scale(w.surface, scalex, scaley);
  141.  
  142. w.display = cairo_create(w.surface);
  143. assert(w.display);
  144.  
  145. w.image = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, w.window_width, w.window_height);
  146. cairo_surface_set_device_scale(w.image, scalex, scaley);
  147.  
  148. w.cairo = cairo_create(w.image);
  149. assert(w.cairo);
  150.  
  151. cairo_select_font_face(w.cairo, "DejaVu Sans Mono", CAIRO_FONT_SLANT_NORMAL, CAIRO_FONT_WEIGHT_NORMAL);
  152.  
  153. cairo_set_line_width(w.cairo, 1. / max(scalex, scaley));
  154. cairo_set_font_size(w.cairo, w.width * 0.0078125);
  155. cairo_set_antialias(w.cairo, CAIRO_ANTIALIAS_SUBPIXEL);
  156.  
  157. cairo_set_source_rgba(w.cairo, 0.0, 0.0, 0.0, 1.0);
  158. cairo_paint(w.cairo);
  159.  
  160. xcb_flush(xcb);
  161. return w;
  162. }
  163.  
  164. void flush(window& w) {
  165. cairo_set_source_surface(w.display, w.image, 0, 0);
  166. cairo_paint(w.display);
  167.  
  168. cairo_surface_flush(w.surface);
  169. xcb_flush(xcb);
  170. }
  171.  
  172. void clear(window& w, rgba color = rgba{0.0, 0.0, 0.0, 1.0}) {
  173. cairo_set_source_rgba(w.cairo, color.r, color.g, color.b, color.a);
  174. cairo_paint(w.cairo);
  175. }
  176. }
  177. }
  178.  
  179. #else
  180. #define debug(...)
  181. #endif
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement