orca/src/graphics/graphics.h

353 lines
13 KiB
C

/************************************************************/ /**
*
* @file: graphics.h
* @author: Martin Fouilleul
* @date: 23/01/2023
* @revision:
*
*****************************************************************/
#ifndef __GRAPHICS_H_
#define __GRAPHICS_H_
#include "app/app.h"
#include "platform/platform.h"
#include "util/typedefs.h"
//------------------------------------------------------------------------------------------
//SECTION: backends selection
//------------------------------------------------------------------------------------------
typedef enum
{
OC_NONE,
OC_METAL,
OC_GL,
OC_GLES,
OC_CANVAS,
OC_HOST
} oc_surface_api;
//NOTE: these macros are used to select which backend to include when building milepost
// they can be overridden by passing them to the compiler command line
#if OC_PLATFORM_MACOS
#ifndef OC_COMPILE_METAL
#define OC_COMPILE_METAL 1
#endif
#ifndef OC_COMPILE_GLES
#define OC_COMPILE_GLES 1
#endif
#ifndef OC_COMPILE_CANVAS
#if !OC_COMPILE_METAL
#error "Canvas surface requires a Metal backend on macOS. Make sure you define OC_COMPILE_METAL to 1."
#endif
#define OC_COMPILE_CANVAS 1
#endif
#define OC_COMPILE_GL 0
#elif OC_PLATFORM_WINDOWS
#ifndef OC_COMPILE_GL
#define OC_COMPILE_GL 1
#endif
#ifndef OC_COMPILE_GLES
#define OC_COMPILE_GLES 1
#endif
#ifndef OC_COMPILE_CANVAS
#if !OC_COMPILE_GL
#error "Canvas surface requires an OpenGL backend on Windows. Make sure you define OC_COMPILE_GL to 1."
#endif
#define OC_COMPILE_CANVAS 1
#endif
#elif PLATFORM_LINUX
#ifndef OC_COMPILE_GL
#define OC_COMPILE_GL 1
#endif
#ifndef OC_COMPILE_CANVAS
#if !OC_COMPILE_GL
#error "Canvas surface requires an OpenGL backend on Linux. Make sure you define OC_COMPILE_GL to 1."
#endif
#define OC_COMPILE_CANVAS 1
#endif
#endif
//NOTE: these macros are used to select backend-specific APIs to include when using milepost
#ifdef OC_EXPOSE_SURFACE_METAL
#include "mtl_surface.h"
#endif
#ifdef OC_EXPOSE_SURFACE_WGL
#include "wgl_surface.h"
#endif
ORCA_API bool oc_is_surface_api_available(oc_surface_api api);
//------------------------------------------------------------------------------------------
//SECTION: graphics surface
//------------------------------------------------------------------------------------------
typedef struct oc_surface
{
u64 h;
} oc_surface;
ORCA_API oc_surface oc_surface_nil(void); //DOC: returns a nil surface
ORCA_API bool oc_surface_is_nil(oc_surface surface); //DOC: true if surface is nil
#if !defined(OC_PLATFORM_ORCA) || !OC_PLATFORM_ORCA
ORCA_API oc_surface oc_surface_create_for_window(oc_window window, oc_surface_api api);
ORCA_API void oc_surface_swap_interval(oc_surface surface, int swap);
ORCA_API bool oc_surface_get_hidden(oc_surface surface);
ORCA_API void oc_surface_set_hidden(oc_surface surface, bool hidden);
#else
ORCA_API oc_surface oc_surface_canvas(); //DOC: creates a surface for use with the canvas API
ORCA_API oc_surface oc_surface_gles(); //DOC: create a surface for use with GLES API
#endif
ORCA_API void oc_surface_destroy(oc_surface surface); //DOC: destroys the surface
ORCA_API void oc_surface_select(oc_surface surface); //DOC: selects the surface in the current thread before drawing
ORCA_API void oc_surface_present(oc_surface surface); //DOC: presents the surface to its window
ORCA_API void oc_surface_deselect(void); //DOC: deselects the current thread's previously selected surface
ORCA_API oc_vec2 oc_surface_get_size(oc_surface surface);
ORCA_API oc_vec2 oc_surface_contents_scaling(oc_surface surface); //DOC: returns the scaling of the surface (pixels = points * scale)
ORCA_API void oc_surface_bring_to_front(oc_surface surface); //DOC: puts surface on top of the surface stack
ORCA_API void oc_surface_send_to_back(oc_surface surface); //DOC: puts surface at the bottom of the surface stack
//------------------------------------------------------------------------------------------
//SECTION: graphics canvas structs
//------------------------------------------------------------------------------------------
typedef struct oc_canvas
{
u64 h;
} oc_canvas;
typedef struct oc_font
{
u64 h;
} oc_font;
typedef struct oc_image
{
u64 h;
} oc_image;
typedef struct oc_color
{
union
{
struct
{
f32 r;
f32 g;
f32 b;
f32 a;
};
f32 c[4];
};
} oc_color;
typedef enum
{
OC_JOINT_MITER = 0,
OC_JOINT_BEVEL,
OC_JOINT_NONE
} oc_joint_type;
typedef enum
{
OC_CAP_NONE = 0,
OC_CAP_SQUARE
} oc_cap_type;
typedef struct oc_font_extents
{
f32 ascent; // the extent above the baseline (by convention a positive value extends above the baseline)
f32 descent; // the extent below the baseline (by convention, positive value extends below the baseline)
f32 leading; // spacing between one row's descent and the next row's ascent
f32 xHeight; // height of the lower case letter 'x'
f32 capHeight; // height of the upper case letter 'M'
f32 width; // maximum width of the font
} oc_font_extents;
typedef struct oc_text_extents
{
f32 xBearing;
f32 yBearing;
f32 width;
f32 height;
f32 xAdvance;
f32 yAdvance;
} oc_text_extents;
//------------------------------------------------------------------------------------------
//SECTION: graphics canvas
//------------------------------------------------------------------------------------------
ORCA_API oc_canvas oc_canvas_nil(void); //DOC: returns a nil canvas
ORCA_API bool oc_canvas_is_nil(oc_canvas canvas); //DOC: true if canvas is nil
ORCA_API oc_canvas oc_canvas_create(void); //DOC: create a new canvas
ORCA_API void oc_canvas_destroy(oc_canvas canvas); //DOC: destroys canvas
ORCA_API oc_canvas oc_canvas_set_current(oc_canvas canvas); //DOC: selects canvas in the current thread
ORCA_API void oc_render(oc_surface surface, oc_canvas canvas); //DOC: renders all canvas commands onto surface
//------------------------------------------------------------------------------------------
//SECTION: fonts
//------------------------------------------------------------------------------------------
ORCA_API oc_font oc_font_nil(void);
ORCA_API oc_font oc_font_create_from_memory(oc_str8 mem, u32 rangeCount, oc_unicode_range* ranges);
ORCA_API void oc_font_destroy(oc_font font);
//NOTE(martin): the following int valued functions return -1 if font is invalid or codepoint is not present in font//
//TODO(martin): add enum error codes
ORCA_API oc_font_extents oc_font_get_extents(oc_font font);
ORCA_API oc_font_extents oc_font_get_scaled_extents(oc_font font, f32 emSize);
ORCA_API f32 oc_font_get_scale_for_em_pixels(oc_font font, f32 emSize);
//NOTE(martin): if you need to process more than one codepoint, first convert your codepoints to glyph indices, then use the
// glyph index versions of the functions, which can take an array of glyph indices.
ORCA_API oc_str32 oc_font_get_glyph_indices(oc_font font, oc_str32 codePoints, oc_str32 backing);
ORCA_API oc_str32 oc_font_push_glyph_indices(oc_font font, oc_arena* arena, oc_str32 codePoints);
ORCA_API u32 oc_font_get_glyph_index(oc_font font, oc_utf32 codePoint);
ORCA_API int oc_font_get_codepoint_extents(oc_font font, oc_utf32 codePoint, oc_text_extents* outExtents);
ORCA_API int oc_font_get_glyph_extents(oc_font font, oc_str32 glyphIndices, oc_text_extents* outExtents);
ORCA_API oc_rect oc_text_bounding_box_utf32(oc_font font, f32 fontSize, oc_str32 text);
ORCA_API oc_rect oc_text_bounding_box(oc_font font, f32 fontSize, oc_str8 text);
//------------------------------------------------------------------------------------------
//SECTION: images
//------------------------------------------------------------------------------------------
ORCA_API oc_image oc_image_nil(void);
ORCA_API bool oc_image_is_nil(oc_image a);
ORCA_API oc_image oc_image_create(oc_surface surface, u32 width, u32 height);
ORCA_API oc_image oc_image_create_from_rgba8(oc_surface surface, u32 width, u32 height, u8* pixels);
ORCA_API oc_image oc_image_create_from_memory(oc_surface surface, oc_str8 mem, bool flip);
ORCA_API oc_image oc_image_create_from_file(oc_surface surface, oc_str8 path, bool flip);
ORCA_API void oc_image_destroy(oc_image image);
ORCA_API void oc_image_upload_region_rgba8(oc_image image, oc_rect region, u8* pixels);
ORCA_API oc_vec2 oc_image_size(oc_image image);
//------------------------------------------------------------------------------------------
//SECTION: atlasing
//------------------------------------------------------------------------------------------
//NOTE: rectangle allocator
typedef struct oc_rect_atlas oc_rect_atlas;
ORCA_API oc_rect_atlas* oc_rect_atlas_create(oc_arena* arena, i32 width, i32 height);
ORCA_API oc_rect oc_rect_atlas_alloc(oc_rect_atlas* atlas, i32 width, i32 height);
ORCA_API void oc_rect_atlas_recycle(oc_rect_atlas* atlas, oc_rect rect);
//NOTE: image atlas helpers
typedef struct oc_image_region
{
oc_image image;
oc_rect rect;
} oc_image_region;
ORCA_API oc_image_region oc_image_atlas_alloc_from_rgba8(oc_rect_atlas* atlas, oc_image backingImage, u32 width, u32 height, u8* pixels);
ORCA_API oc_image_region oc_image_atlas_alloc_from_data(oc_rect_atlas* atlas, oc_image backingImage, oc_str8 data, bool flip);
ORCA_API oc_image_region oc_image_atlas_alloc_from_file(oc_rect_atlas* atlas, oc_image backingImage, oc_str8 path, bool flip);
ORCA_API void oc_image_atlas_recycle(oc_rect_atlas* atlas, oc_image_region imageRgn);
//------------------------------------------------------------------------------------------
//SECTION: transform, viewport and clipping
//------------------------------------------------------------------------------------------
ORCA_API void oc_matrix_push(oc_mat2x3 matrix);
ORCA_API void oc_matrix_pop(void);
ORCA_API oc_mat2x3 oc_matrix_top();
ORCA_API void oc_clip_push(f32 x, f32 y, f32 w, f32 h);
ORCA_API void oc_clip_pop(void);
ORCA_API oc_rect oc_clip_top();
//------------------------------------------------------------------------------------------
//SECTION: graphics attributes setting/getting
//------------------------------------------------------------------------------------------
ORCA_API void oc_set_color(oc_color color);
ORCA_API void oc_set_color_rgba(f32 r, f32 g, f32 b, f32 a);
ORCA_API void oc_set_width(f32 width);
ORCA_API void oc_set_tolerance(f32 tolerance);
ORCA_API void oc_set_joint(oc_joint_type joint);
ORCA_API void oc_set_max_joint_excursion(f32 maxJointExcursion);
ORCA_API void oc_set_cap(oc_cap_type cap);
ORCA_API void oc_set_font(oc_font font);
ORCA_API void oc_set_font_size(f32 size);
ORCA_API void oc_set_text_flip(bool flip);
ORCA_API void oc_set_image(oc_image image);
ORCA_API void oc_set_image_source_region(oc_rect region);
ORCA_API oc_color oc_get_color(void);
ORCA_API f32 oc_get_width(void);
ORCA_API f32 oc_get_tolerance(void);
ORCA_API oc_joint_type oc_get_joint(void);
ORCA_API f32 oc_get_max_joint_excursion(void);
ORCA_API oc_cap_type oc_get_cap(void);
ORCA_API oc_font oc_get_font(void);
ORCA_API f32 oc_get_font_size(void);
ORCA_API bool oc_get_text_flip(void);
ORCA_API oc_image oc_get_image();
ORCA_API oc_rect oc_get_image_source_region();
//------------------------------------------------------------------------------------------
//SECTION: path construction
//------------------------------------------------------------------------------------------
ORCA_API oc_vec2 oc_get_position(void);
ORCA_API void oc_move_to(f32 x, f32 y);
ORCA_API void oc_line_to(f32 x, f32 y);
ORCA_API void oc_quadratic_to(f32 x1, f32 y1, f32 x2, f32 y2);
ORCA_API void oc_cubic_to(f32 x1, f32 y1, f32 x2, f32 y2, f32 x3, f32 y3);
ORCA_API void oc_close_path(void);
ORCA_API oc_rect oc_glyph_outlines(oc_str32 glyphIndices);
ORCA_API void oc_codepoints_outlines(oc_str32 string);
ORCA_API void oc_text_outlines(oc_str8 string);
//------------------------------------------------------------------------------------------
//SECTION: clear/fill/stroke
//------------------------------------------------------------------------------------------
ORCA_API void oc_clear(void);
ORCA_API void oc_fill(void);
ORCA_API void oc_stroke(void);
//------------------------------------------------------------------------------------------
//SECTION: shapes helpers
//------------------------------------------------------------------------------------------
ORCA_API void oc_rectangle_fill(f32 x, f32 y, f32 w, f32 h);
ORCA_API void oc_rectangle_stroke(f32 x, f32 y, f32 w, f32 h);
ORCA_API void oc_rounded_rectangle_fill(f32 x, f32 y, f32 w, f32 h, f32 r);
ORCA_API void oc_rounded_rectangle_stroke(f32 x, f32 y, f32 w, f32 h, f32 r);
ORCA_API void oc_ellipse_fill(f32 x, f32 y, f32 rx, f32 ry);
ORCA_API void oc_ellipse_stroke(f32 x, f32 y, f32 rx, f32 ry);
ORCA_API void oc_circle_fill(f32 x, f32 y, f32 r);
ORCA_API void oc_circle_stroke(f32 x, f32 y, f32 r);
ORCA_API void oc_arc(f32 x, f32 y, f32 r, f32 arcAngle, f32 startAngle);
//NOTE: image helpers
ORCA_API void oc_image_draw(oc_image image, oc_rect rect);
ORCA_API void oc_image_draw_region(oc_image image, oc_rect srcRegion, oc_rect dstRegion);
#endif //__GRAPHICS_H_