ezgl  1.0.1
An Easy Graphics & GUI Library
graphics.hpp
1 /*
2  * Copyright 2019-2022 University of Toronto
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  *
16  * Authors: Mario Badr, Sameh Attia, Tanner Young-Schultz and Vaughn Betz
17  */
18 
19 #ifndef EZGL_GRAPHICS_HPP
20 #define EZGL_GRAPHICS_HPP
21 
22 #include "ezgl/color.hpp"
23 #include "ezgl/point.hpp"
24 #include "ezgl/rectangle.hpp"
25 #include "ezgl/camera.hpp"
26 
27 #include <cairo.h>
28 #include <gdk/gdk.h>
29 
30 #ifdef CAIRO_HAS_XLIB_SURFACE
31 #ifdef GDK_WINDOWING_X11
32 #include <cairo-xlib.h>
33 
34 // Speed up draw calls by using X11 instead of cairo wherever possible. X11 is about twice as fast.
35 // Cairo is always used if we're using a partially transparent color, so opaque rendering is faster.
36 #define EZGL_USE_X11
37 #endif
38 #endif
39 
40 #include <functional>
41 #include <string>
42 #include <vector>
43 #include <cfloat>
44 #include <cmath>
45 #include <algorithm>
46 
47 namespace ezgl {
48 
52 typedef cairo_surface_t surface;
53 
67  SCREEN
68 };
69 
73 enum class justification {
77  center,
81  left,
85  right,
89  top,
93  bottom
94 };
95 
101 enum class font_slant : int {
105  normal = CAIRO_FONT_SLANT_NORMAL,
106 
110  italic = CAIRO_FONT_SLANT_ITALIC,
111 
115  oblique = CAIRO_FONT_SLANT_OBLIQUE
116 };
117 
121 enum class font_weight : int {
125  normal = CAIRO_FONT_WEIGHT_NORMAL,
126 
130  bold = CAIRO_FONT_WEIGHT_BOLD
131 };
132 
136 enum class line_cap : int {
140  butt = CAIRO_LINE_CAP_BUTT,
141 
146  round = CAIRO_LINE_CAP_ROUND
147 };
148 
152 enum class line_dash : int {
156  none,
157 
162 };
163 
173 class renderer {
174 public:
180  void set_coordinate_system(t_coordinate_system new_coordinate_system);
181 
192  void set_visible_world(rectangle new_world);
193 
200 
207 
216 
217  /**** Functions to set graphics attributes (for all subsequent drawing calls). ****/
218 
224  void set_color(color new_color);
225 
232  void set_color(color new_color, uint_fast8_t alpha);
233 
242  void set_color(uint_fast8_t red, uint_fast8_t green, uint_fast8_t blue, uint_fast8_t alpha = 255);
243 
250 
257 
266  void set_line_width(int width);
267 
274  void set_font_size(double new_size);
275 
283  void format_font(std::string const &family, font_slant slant, font_weight weight);
284 
293  void
294  format_font(std::string const &family, font_slant slant, font_weight weight, double new_size);
295 
301  void set_text_rotation(double degrees);
302 
309 
316 
317  /**** Functions to draw various graphics primitives ****/
318 
325  void draw_line(point2d start, point2d end);
326 
333  void draw_rectangle(point2d start, point2d end);
334 
342  void draw_rectangle(point2d start, double width, double height);
343 
350 
357  void fill_rectangle(point2d start, point2d end);
358 
366  void fill_rectangle(point2d start, double width, double height);
367 
374 
383  void fill_poly(std::vector<point2d> const &points);
384 
395  double radius_x,
396  double radius_y,
397  double start_angle,
398  double extent_angle);
399 
408  void draw_arc(point2d center, double radius, double start_angle, double extent_angle);
409 
420  double radius_x,
421  double radius_y,
422  double start_angle,
423  double extent_angle);
424 
433  void fill_arc(point2d center, double radius, double start_angle, double extent_angle);
434 
441  void draw_text(point2d point, std::string const &text);
442 
454  void draw_text(point2d point, std::string const &text, double bound_x, double bound_y);
455 
465  void draw_surface(surface *p_surface, point2d anchor_point, double scale_factor = 1);
466 
474  static surface *load_png(const char *file_path);
475 
481  static void free_surface(surface *surface);
482 
487 
488 protected:
489  // Only the canvas class can create a renderer.
490  friend class canvas;
491 
495  using transform_fn = std::function<point2d(point2d)>;
496 
503  renderer(cairo_t *cairo, transform_fn transform, camera *m_camera, cairo_surface_t *m_surface);
504 
511  void update_renderer(cairo_t *cairo, cairo_surface_t *m_surface);
512 
513 private:
514  void draw_rectangle_path(point2d start, point2d end, bool fill_flag);
515 
516  void draw_arc_path(point2d center,
517  double radius,
518  double start_angle,
519  double extent_angle,
520  double stretch_factor,
521  bool fill_flag);
522 
523  // Pre-clipping function
524  bool rectangle_off_screen(rectangle rect);
525 
526  // Current coordinate system (World is the default)
527  t_coordinate_system current_coordinate_system = WORLD;
528 
529  // A non-owning pointer to a cairo graphics context.
530  cairo_t *m_cairo;
531 
532 #ifdef EZGL_USE_X11
533  // The x11 drawable
534  Drawable x11_drawable;
535 
536  // The x11 display
537  Display *x11_display = nullptr;
538 
539  // The x11 context
540  GC x11_context;
541 
542  // Transparency flag, if set, cairo will be used
543  bool transparency_flag = false;
544 #endif
545 
546  transform_fn m_transform;
547 
548  //A non-owning pointer to camera object
549  camera *m_camera;
550 
551  // Drawing attributes declared and given reasonable defaults below.
552 
553  // the rotation angle variable used in rotating text
554  double rotation_angle = 0;
555 
556  // Current horizontal justification (used for text and surfaces)
557  justification horiz_justification = justification::center;
558 
559  // Current vertical justification (used for text and surfaces)
560  justification vert_justification = justification::center;
561 
562  // Current line width
563  int current_line_width = 0;
564 
565  // Current line cap
566  line_cap current_line_cap = line_cap::butt;
567 
568  // Current line dash
569  line_dash current_line_dash = line_dash::none;
570 
571  // Current color
572  color current_color = {0, 0, 0, 255};
573 };
574 }
575 
576 #endif //EZGL_GRAPHICS_HPP
Manages the transformations between coordinate systems.
Definition: camera.hpp:40
Responsible for creating, destroying, and maintaining the rendering context of a GtkWidget.
Definition: canvas.hpp:54
Represents a two-dimensional point.
Definition: point.hpp:27
Represents a rectangle as two diagonally opposite points.
Definition: rectangle.hpp:31
Provides functions to draw primitives (e.g., lines, shapes) to a rendering context (the MainCanvas).
Definition: graphics.hpp:173
void set_color(uint_fast8_t red, uint_fast8_t green, uint_fast8_t blue, uint_fast8_t alpha=255)
Change the color for subsequent draw calls.
rectangle world_to_screen(const rectangle &box)
Get the screen coordinates (pixel locations) of the world coordinate rectangle box.
void fill_rectangle(rectangle r)
Draw a filled in rectangle.
void fill_poly(std::vector< point2d > const &points)
Draw a filled polygon The polygon can have an arbitrary shape and be convex or non-convex,...
void set_line_cap(line_cap cap)
Change how line endpoints will be rendered in subsequent draw calls.
void draw_text(point2d point, std::string const &text)
Draw text justified at the chosen point, according to the current justification.
static void free_surface(surface *surface)
Free a surface.
void set_text_rotation(double degrees)
set the rotation_angle at which subsequent text drawing should render.
void set_color(color new_color)
Change the color for subsequent draw calls.
rectangle get_visible_world()
Get the current visible bounds of the world.
void update_renderer(cairo_t *cairo, cairo_surface_t *m_surface)
Update the renderer when the cairo surface/context changes.
void fill_elliptic_arc(point2d center, double radius_x, double radius_y, double start_angle, double extent_angle)
Draw a filled in elliptic arc.
void draw_arc(point2d center, double radius, double start_angle, double extent_angle)
Draw the outline of an arc.
void fill_arc(point2d center, double radius, double start_angle, double extent_angle)
Draw a filled in arc.
void set_horiz_justification(justification horiz_just)
set horizontal justification; used for text and surfaces.
void draw_rectangle(point2d start, point2d end)
Draw the outline a rectangle.
rectangle get_visible_screen()
Get the current visible bounds of the screen in pixel coordinates.
void set_coordinate_system(t_coordinate_system new_coordinate_system)
Change the current coordinate system.
void draw_rectangle(point2d start, double width, double height)
Draw the outline of a rectangle.
std::function< point2d(point2d)> transform_fn
A callback for transforming points from one coordinate system to another.
Definition: graphics.hpp:495
void draw_text(point2d point, std::string const &text, double bound_x, double bound_y)
Draw text if it fits in the specified bounds; otherwise not drawn.
void format_font(std::string const &family, font_slant slant, font_weight weight)
Change the font.
void format_font(std::string const &family, font_slant slant, font_weight weight, double new_size)
Change the font.
void set_visible_world(rectangle new_world)
Set the visible bounds of the world.
void set_vert_justification(justification vert_just)
set vertical justification; used for text and surfaces.
void set_line_width(int width)
Set the line width.
void draw_surface(surface *p_surface, point2d anchor_point, double scale_factor=1)
Draw a surface.
void fill_rectangle(point2d start, double width, double height)
Draw a filled in rectangle.
void set_color(color new_color, uint_fast8_t alpha)
Change the color for subsequent draw calls.
static surface * load_png(const char *file_path)
load a png image into a bitmap surface
renderer(cairo_t *cairo, transform_fn transform, camera *m_camera, cairo_surface_t *m_surface)
Constructor.
void draw_rectangle(rectangle r)
Draw the outline of a rectangle.
void draw_line(point2d start, point2d end)
Draw a line.
void set_font_size(double new_size)
Change the font size.
~renderer()
Destructor.
void fill_rectangle(point2d start, point2d end)
Draw a filled in rectangle.
void draw_elliptic_arc(point2d center, double radius_x, double radius_y, double start_angle, double extent_angle)
Draw the outline of an elliptic arc.
void set_line_dash(line_dash dash)
Change the dash style of the line for subsequent draw calls.
A library for creating a graphical user interface.
Definition: application.hpp:40
line_dash
The dash style of a line.
Definition: graphics.hpp:152
@ none
No dashes in the line (i.e., solid).
@ asymmetric_5_3
Dash to whitespace ratio is 5:3.
font_weight
The weight of the font.
Definition: graphics.hpp:121
@ bold
Bold font weight.
@ normal
No additional weight.
line_cap
The shape of a line's start and end point.
Definition: graphics.hpp:136
@ butt
Start and stop the line exactly where it begins/ends.
@ round
Each end of the line has circles.
font_slant
The slant of the font.
Definition: graphics.hpp:101
@ italic
Slant is more calligraphic.
@ oblique
Slanted to the right.
@ normal
No slant.
t_coordinate_system
Available coordinate systems.
Definition: graphics.hpp:57
@ WORLD
Default coordinate system; specified by the user as any desired range.
Definition: graphics.hpp:63
@ SCREEN
Screen (pixel) coordinate system.
Definition: graphics.hpp:67
justification
Justification options used for text and surfaces.
Definition: graphics.hpp:73
@ bottom
Bottom justification: used for vertical justification.
@ right
Right justification: used for horizontal justification.
@ left
Left justification: used for horizontal justification.
@ center
Center Justification: used for both vertical and horizontal justification.
@ top
Top justification: used for vertical justification.
cairo_surface_t surface
define ezgl::surface type used for drawing png bitmaps
Definition: graphics.hpp:52
Represents a color as a mixture or red, green, and blue as well as the transparency level.
Definition: color.hpp:31