blob: 9320096eee383d67d6bd00d42b36535cd2eaa7ba [file] [log] [blame]
#ifndef GRAPHICS_STATE_H
#define GRAPHICS_STATE_H
#include "easygl_constants.h"
#include "fontcache.h"
/**********************************
* Common Preprocessor Directives *
**********************************/
#include <stdlib.h>
#include <stdio.h>
#include <string>
#include <iostream>
#include <algorithm>
#include <vector>
#include <queue>
#include <unordered_map>
#include <sys/timeb.h>
#include <math.h>
#ifdef X11
#include <X11/Xlib.h>
#include <X11/Xutil.h>
#include <X11/Xos.h>
#include <X11/Xatom.h>
#include <X11/Xft/Xft.h>
#include <cairo.h>
#include <cairo-xlib.h>
#endif
#ifdef WIN32
#include <windows.h>
#include <WindowsX.h>
#endif
#define BUFSIZE 1000
#ifdef X11
/*************************************************************
* X11 Structure Definitions *
*************************************************************/
/* Structure used to store X Windows state variables.
* display: Structure containing information needed to
* communicate with Xlib.
* screen_num: Value the Xlib server uses to identify every
* connected screen.
* current_font: the currently selected font.
* toplevel, menu, textarea: Toplevel window and 2 child windows.
* gc_normal, gc_xor, current_gc: Graphic contexts for drawing
* in the graphics area. (gc_normal for overwrite
* drawing, gc_xor for rubber band drawing, and
* current_gc is the current gc used)
* gc_menus: Graphic context for drawing in the status message
* and menu area
* xft_menutextcolor: the XFT colour used for drawing button and menu text.
* xft_currentcolor: the XFT colour used for drawing normal text. Is kept in
* sync with gl_state.foreground_color
*/
class t_x11_state {
public:
t_x11_state();
~t_x11_state();
Display *display = nullptr;
int screen_num;
Window toplevel, menu, textarea;
GC gc_normal, gc_xor, gc_menus, current_gc;
XftDraw *toplevel_draw = nullptr,
*menu_draw = nullptr,
*textarea_draw = nullptr;
XftColor xft_menutextcolor;
XftColor xft_currentcolor;
XVisualInfo visual_info;
Colormap colormap_to_use;
// single multi-buffering variables
Drawable* draw_area = nullptr;
Pixmap draw_buffer;
XftDraw *draw_buffer_draw = nullptr,
*draw_area_draw = nullptr;
// window attributes here so I only have to call XGetWindowAttributes on resize
XWindowAttributes attributes;
// Cairo related things
cairo_surface_t *cairo_surface = nullptr;
cairo_t *ctx = nullptr;
static t_x11_state *getInstance();
private:
// Pointer to the most recently constructed state. Is set to NULL upon any destruction
static t_x11_state *instance;
};
#endif // X11
#ifdef WIN32
/*************************************************************
* WIN32 Structure Definitions *
*************************************************************/
/* Flag used for the "window" button. Before the user presses the button, the
* "window" operation is in WINDOW_DEACTIVATED state. After user presses the
* button, the operation proceeds to WAITING_FOR_FIRST_CORNER_POINT state and
* waits for the user to click the first point in the graphics area as the first
* corner for rubber band drawing. After user clicks the first point, the operation
* proceeds to WAITING_FOR_SECOND_CORNER_POINT and waits for the user to click on
* the second point to define the rectangular region enclosed by the rubber band.
* Then the application window will zoom in to the region defined and the "window"
* operation goes back to WINDOW_DEACTIVATED.
*/
typedef enum {
WINDOW_DEACTIVATED = 0,
WAITING_FOR_FIRST_CORNER_POINT,
WAITING_FOR_SECOND_CORNER_POINT
} t_window_button_state;
/* Structure used to store Win32 state variables.
* InEventLoop: Whether in event_loop(); used to indicate if part of the application window need
* to be redrawn when system makes request by sending WM_PAINT message in the
* WIN32_GraphicsWND callback function.
* windowAdjustFlag: Flag used for the "Window" button operation. This variable has 3 states
* which are defined above.
* adjustButton: Holds the index of the "Window" button in the array of buttons created
* adjustRect: Used for the "Window" button operation. Holds the boundary coordinates (in screen
* pixels) of the region enclosed by the rubber band.
* hMainWnd, hGraphicsWnd, hButtonsWnd, hStatusWnd: Handles to the top level window and
* 3 subwindows.
* hGraphicsDC: Handle to the graphics device context.
* hGraphicsPen, hGraphicsBrush, hGrayBrush, hGraphicsFont: Handles to Windows GDI objects used
* for drawing. (hGraphicsPen for drawing lines, hGraphicsBrush for filling shapes,
* and hGrayBrush for filling the background of the status message and menu areas)
*/
class t_win32_state {
public:
t_win32_state();
~t_win32_state();
bool InEventLoop;
t_window_button_state windowAdjustFlag;
int adjustButton;
RECT adjustRect;
HWND hMainWnd, hGraphicsWnd, hButtonsWnd, hStatusWnd;
HDC hGraphicsDC;
HPEN hGraphicsPen;
HBRUSH hGraphicsBrush, hGrayBrush;
HFONT hGraphicsFont;
static t_win32_state *getInstance();
private:
// Pointer to the most recently constructed state. Is set to NULL upon any destruction
static t_win32_state *instance;
};
#endif // WIN32
/*************************************************************
* Operating System Independent *
*************************************************************/
/* Used to define where the output of drawscreen (graphics primitives in the user-controlled
* area) currently goes to: the screen or a postscript file.
*/
typedef enum {
SCREEN = 0,
POSTSCRIPT = 1
} t_display_type;
/* Structure used to store overall graphics state variables.
* initialized: true if the graphics window & state have been
* created and initialized, false otherwise.
* disp_type: Selects SCREEN or POSTSCRIPT
* background_color: colour of the window (or page for PS) background colour
* foreground_color: current color in the graphics context
* currentlinestyle: current linestyle in the graphics context
* currentlinewidth: current linewidth in the graphics context
* currentfontsize: current font size in the graphics context
* currentfontrotation: current text rotation angle, in degrees
* Using integer degrees to avoid huge numbers of distinct rotations
* that cause many (slow) font loads.
* current_draw_to: OFF_SCREEN buffer or ON_SCREEN (window). Controls double buffering.
* current_draw_mode: select DRAW_NORMAL (for overwrite) or DRAW_XOR (for rubber-banding)
* ps: for PostScript output
* ProceedPressed: whether the Proceed button has been pressed
* statusMessage: user message to display
* font_info: a font cache
* get_keypress_input: whether keypresses are sent back to callback functions
* get_mouse_move_input: whether mouse movements are sent back to callback functions
* redraw_needed: true if there has been an expose or other event that requires a
* redraw, but we haven't done one yet.
* disable_event_loop: set for automarking of student assignments where
* you don't want to hang in the event_loop
* redirect_to_postscript: when set, a call to event_loop will instead draw to
* postscript. Useful for automarking.
*
* Need to initialize graphics_loaded to false, since checking it is
* how we avoid multiple construction or destruction of the graphics
* window. Initializing display type and background color index is not
* necessary since they are set in init_graphics(), but doing so
* just for safety.
*/
struct t_gl_state {
bool initialized;
t_display_type disp_type;
t_color background_color;
t_color foreground_color;
int currentlinestyle;
int currentlinecap;
int currentlinewidth;
int currentfontsize;
int currentfontrotation;
t_coordinate_system currentcoordinatesystem;
t_draw_to current_draw_to;
e_draw_mode current_draw_mode;
FILE *ps = nullptr;
bool ProceedPressed;
char statusMessage[BUFSIZE];
FontCache font_info;
bool get_keypress_input, get_mouse_move_input;
bool redraw_needed;
bool disable_event_loop = false;
bool redirect_to_postscript = false;
t_gl_state() {
initialized = false;
disp_type = SCREEN;
currentlinecap = 0;
currentlinestyle = 0;
currentcoordinatesystem = GL_WORLD;
background_color = t_color(0xFF, 0xFF, 0xCC);
disable_event_loop = false;
redirect_to_postscript = false;
}
};
#endif // GRAPHICS_STATE_H