OpenFPGA/libs/EXTERNAL/libezgl/include/ezgl/graphics.hpp

540 lines
13 KiB
C++

/*
* Copyright 2019 University of Toronto
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Authors: Mario Badr, Sameh Attia and Tanner Young-Schultz
*/
#ifndef EZGL_GRAPHICS_HPP
#define EZGL_GRAPHICS_HPP
#include "ezgl/color.hpp"
#include "ezgl/point.hpp"
#include "ezgl/rectangle.hpp"
#include "ezgl/camera.hpp"
#include <cairo.h>
#include <gdk/gdk.h>
#ifdef CAIRO_HAS_XLIB_SURFACE
#ifdef GDK_WINDOWING_X11
#include <cairo-xlib.h>
// Speed up draw calls by using X11 instead of cairo wherever possible.
#define EZGL_USE_X11
#endif
#endif
#include <functional>
#include <string>
#include <vector>
#include <cfloat>
#include <cmath>
#include <algorithm>
namespace ezgl {
/**
* define ezgl::surface type used for drawing pngs
*/
typedef cairo_surface_t surface;
/**
* Available coordinate systems
*/
enum t_coordinate_system {
/**
* Default coordinate system
*/
WORLD,
/**
* Screen coordinate system. Screen Coordinates are not transformed so the drawn objects do not pan or zoom.
*/
SCREEN
};
/**
* Text justification options
*/
enum class text_just {
/**
* Center Justification: used for both vertical and horizontal justification
*/
center,
/**
* Left justification: used for horizontal justification
*/
left,
/**
* Right justification: used for horizontal justification
*/
right,
/**
* Top justification: used for vertical justification
*/
top,
/**
* Bottom justification: used for vertical justification
*/
bottom
};
/**
* The slant of the font.
*
* This enum is setup to match with the cairo graphics library and should not be changed.
*/
enum class font_slant : int {
/**
* No slant.
*/
normal = CAIRO_FONT_SLANT_NORMAL,
/**
* Slant is more calligraphic. Make sure the font you're using has an italic design, otherwise it may look ugly.
*/
italic = CAIRO_FONT_SLANT_ITALIC,
/**
* Slanted to the right.
*/
oblique = CAIRO_FONT_SLANT_OBLIQUE
};
/**
* The weight of the font.
*/
enum class font_weight : int {
/**
* No additional weight.
*/
normal = CAIRO_FONT_WEIGHT_NORMAL,
/**
* Bold font weight.
*/
bold = CAIRO_FONT_WEIGHT_BOLD
};
/**
* The shape of a line's start and end point.
*/
enum class line_cap : int {
/**
* Start and stop the line exactly where it begins/ends.
*/
butt = CAIRO_LINE_CAP_BUTT,
/**
* Each end of the line has circles.
*/
round = CAIRO_LINE_CAP_ROUND
};
/**
* The dash style of a line.
*/
enum class line_dash : int {
/**
* No dashes in the line (i.e., solid).
*/
none,
/**
* Dash to whitespace ratio is 5:3.
*/
asymmetric_5_3
};
/**
* Provides functions to draw primitives (e.g., lines, shapes) to a rendering context.
*
* The renderer modifies a cairo_t context based on draw calls. The renderer uses an ezgl::camera object to convert
* world coordinates into cairo's expected coordinate system.
*/
class renderer {
public:
/**
* Change the current coordinate system
*
* @param new_coordinate_system The drawing coordinate system SCREEN or WORLD
*/
void set_coordinate_system(t_coordinate_system new_coordinate_system);
/**
* Set the visible bounds of the world
*
* The function preserves the aspect ratio of the initial world
*
* @param new_world The new visible bounds of the world
*/
void set_visible_world(rectangle new_world);
/**
* Get the current visible bounds of the world
*/
rectangle get_visible_world();
/**
* Get the current visible bounds of the screen
*/
rectangle get_visible_screen();
/**
* Get the screen coordinates (i.e. pixel locations) of the world coordinate rectangle box
*
* @param box: a rectangle in world coordinates
*/
rectangle world_to_screen(const rectangle& box);
/**** Functions to set graphics attributes (for all subsequent drawing calls). ****/
/**
* Change the color for subsequent draw calls.
*
* @param new_color The new color to use.
*/
void set_color(color new_color);
/**
* Change the color for subsequent draw calls.
*
* @param new_color The new color to use.
* @param alpha Overwrite the alpha channel in the chosen color.
*/
void set_color(color new_color, uint_fast8_t alpha);
/**
* Change the color for subsequent draw calls.
*
* @param red The amount of red to use, between 0 and 255.
* @param green The amount of green to use, between 0 and 255.
* @param blue The amount of blue to use, between 0 and 255.
* @param alpha The transparency level (0 is fully transparent, 255 is opaque).
*/
void set_color(uint_fast8_t red, uint_fast8_t green, uint_fast8_t blue, uint_fast8_t alpha = 255);
/**
* Change how line endpoints will be rendered in subsequent draw calls.
*/
void set_line_cap(line_cap cap);
/**
* Change the dash style of the line.
*/
void set_line_dash(line_dash dash);
/**
* Set the line width.
*
* @param width The width in pixels.
* A value of 0 is still one pixel wide but about 100x faster
* to draw than other line widths.
*/
void set_line_width(int width);
/**
* Change the font size.
*
* @param new_size The new size text should be drawn at.
*/
void set_font_size(double new_size);
/**
* Change the font.
*
* @param family The font family to use (e.g., serif)
* @param slant The slant to use (e.g., italic)
* @param weight The weight of the font (e.g., bold)
*/
void format_font(std::string const &family, font_slant slant, font_weight weight);
/**
* Change the font.
*
* @param family The font family to use (e.g., serif)
* @param slant The slant to use (e.g., italic)
* @param weight The weight of the font (e.g., bold)
* @param new_size The new size text should be drawn at.
*/
void
format_font(std::string const &family, font_slant slant, font_weight weight, double new_size);
/**
* set the rotation_angle variable that is used in rotating text.
*
* @param degrees The angle by which the text should rotate, in degrees.
*/
void set_text_rotation(double degrees);
/**
* set horizontal text justification.
*
* @param horiz_just Options: center, left and right justification.
*/
void set_horiz_text_just(text_just horiz_just);
/**
* set vertical text justification.
*
* @param vert_just Options: center, top and bottom justification.
*/
void set_vert_text_just(text_just vert_just);
/**** Functions to draw various graphics primitives ****/
/**
* Draw a line.
*
* @param start The start point of the line, in pixels.
* @param end The end point of the line, in pixels.
*/
void draw_line(point2d start, point2d end);
/**
* Draw the outline a rectangle.
*
* @param start The start point of the rectangle, in pixels.
* @param end The end point of the rectangle, in pixels.
*/
void draw_rectangle(point2d start, point2d end);
/**
* Draw the outline of a rectangle.
*
* @param start The start point of the rectangle, in pixels.
* @param width How wide the rectangle is, in pixels.
* @param height How high the rectangle is, in pixels.
*/
void draw_rectangle(point2d start, double width, double height);
/**
* Draw the outline of a rectangle.
*/
void draw_rectangle(rectangle r);
/**
* Draw a filled in rectangle.
*
* @param start The start point of the rectangle, in pixels.
* @param end The end point of the rectangle, in pixels.
*/
void fill_rectangle(point2d start, point2d end);
/**
* Draw a filled in rectangle.
*
* @param start The start point of the rectangle, in pixels.
* @param width How wide the rectangle is, in pixels.
* @param height How high the rectangle is, in pixels.
*/
void fill_rectangle(point2d start, double width, double height);
/**
* Draw a filled in rectangle.
*/
void fill_rectangle(rectangle r);
/**
* Draw a filled polygon.
*
* @param points The points to draw. The first and last points are connected to close the polygon.
*/
void fill_poly(std::vector<point2d> const &points);
/**
* Draw the outline of an elliptic arc.
*
* @param center The center of the arc, in pixels.
* @param radius_x The x radius of the elliptic arc, in pixels.
* @param radius_y The y radius of the elliptic arc, in pixels.
* @param start_angle The starting angle of the arc, in degrees.
* @param extent_angle The extent angle of the arc, in degrees.
*/
void draw_elliptic_arc(point2d center,
double radius_x,
double radius_y,
double start_angle,
double extent_angle);
/**
* Draw the outline of an arc.
*
* @param center The center of the arc, in pixels.
* @param radius The radius of the arc, in pixels.
* @param start_angle The starting angle of the arc, in degrees.
* @param extent_angle The extent angle of the arc, in degrees.
*/
void draw_arc(point2d center, double radius, double start_angle, double extent_angle);
/**
* Draw a filled in elliptic arc.
*
* @param center The center of the arc, in pixels.
* @param radius_x The x radius of the elliptic arc, in pixels.
* @param radius_y The y radius of the elliptic arc, in pixels.
* @param start_angle The starting angle of the arc, in degrees.
* @param extent_angle The extent angle of the arc, in degrees.
*/
void fill_elliptic_arc(point2d center,
double radius_x,
double radius_y,
double start_angle,
double extent_angle);
/**
* Draw a filled in arc.
*
* @param center The center of the arc, in pixels.
* @param radius The radius of the arc, in pixels.
* @param start_angle The starting angle of the arc, in degrees.
* @param extent_angle The extent angle of the arc, in degrees.
*/
void fill_arc(point2d center, double radius, double start_angle, double extent_angle);
/**
* Draw text.
*
* @param point The point where the text is drawn, in pixels.
* @param text The text to draw.
*/
void draw_text(point2d point, std::string const &text);
/**
* Draw text with bounds.
*
* @param point The point where the text is drawn, in pixels.
* @param text The text to draw.
* @param bound_x The maximum allowed width of the text
* @param bound_y The maximum allowed height of the text
*/
void draw_text(point2d point, std::string const &text, double bound_x, double bound_y);
/**
* Draw a surface
*
* @param surface The surface to draw
* @param top_left The corner point of the drawn surface.
*/
void draw_surface(surface *surface, point2d top_left);
/**
* load a png image
*
* @param file_path The path to the png image.
*
* @return a pointer to the created surface. Should be freed using free_surface()
*/
static surface *load_png(const char *file_path);
/**
* Free a surface
*
* @param surface The surface to destroy
*/
static void free_surface(surface *surface);
/**
* Destructor.
*/
~renderer();
protected:
// Only the canvas class can create a renderer.
friend class canvas;
/**
* A callback for transforming points from one coordinate system to another.
*/
using transform_fn = std::function<point2d(point2d)>;
/**
* Constructor.
*
* @param cairo The cairo graphics state.
* @param transform The function to use to transform points to cairo's coordinate system.
*/
renderer(cairo_t *cairo, transform_fn transform, camera *m_camera, cairo_surface_t *m_surface);
/**
* Update the renderer when the cairo surface/context changes
*
* @param cairo The new cairo graphics state
* @param m_surface The new cairo surface
*/
void update_renderer(cairo_t *cairo, cairo_surface_t *m_surface);
private:
void draw_rectangle_path(point2d start, point2d end, bool fill_flag);
void draw_arc_path(point2d center,
double radius,
double start_angle,
double extent_angle,
double stretch_factor,
bool fill_flag);
// Pre-clipping function
bool rectangle_off_screen(rectangle rect);
// Current coordinate system (World is the default)
t_coordinate_system current_coordinate_system = WORLD;
// A non-owning pointer to a cairo graphics context.
cairo_t *m_cairo;
#ifdef EZGL_USE_X11
// The x11 drawable
Drawable x11_drawable;
// The x11 display
Display *x11_display = nullptr;
// The x11 context
GC x11_context;
// Transparency flag, if set, cairo will be used
bool transparency_flag = false;
#endif
transform_fn m_transform;
//A non-owning pointer to camera object
camera *m_camera;
// the rotation angle variable used in rotating text
double rotation_angle;
// Current horizontal text justification
text_just horiz_text_just = text_just::center;
// Current vertical text justification
text_just vert_text_just = text_just::center;
// Current line width
int current_line_width = 1;
// Current line cap
line_cap current_line_cap = line_cap::butt;
// Current line dash
line_dash current_line_dash = line_dash::none;
// Current color
color current_color = {0, 0, 0, 255};
};
}
#endif //EZGL_GRAPHICS_HPP