#ifndef RGL_H #define RGL_H #ifdef RGL_DEBUG static char *ERROR_MESSAGE; #define RGL_CRASH(text) \ do { \ ERROR_MESSAGE = text; \ __builtin_trap(); \ } while (0) #define RGL_ASSERT(cond, text) \ if (!(cond)) { \ RGL_CRASH(text); \ } #else #define RGL_CRASH(text) #define RGL_ASSERT(cond, text) #endif static int RGL_ABS(int n) { return n < 0 ? -n : n; } /* Memory */ typedef struct { unsigned int size; unsigned int capacity; unsigned char *data; } RGL_Arena; void *RGL_ArenaAlloc(RGL_Arena *arena, unsigned int size); unsigned int RGL_ArenaCheckpoint(RGL_Arena *arena); void RGL_ArenaRollback(RGL_Arena *arena, unsigned int checkpoint); void RGL_ArenaReset(RGL_Arena *arena); /* Math */ typedef unsigned int RGL_Fixed; #define RGL_SUBPIXEL_SHIFT 8 #define RGL_SUBPIXEL_SCALE 256 #define RGL_SUBPIXEL_MASK 255 static RGL_Fixed RGL_GetFixedI(int x) { return (RGL_Fixed)(x << RGL_SUBPIXEL_SHIFT); } static RGL_Fixed RGL_GetFixedF(float x) { return (RGL_Fixed)(x * RGL_SUBPIXEL_SCALE); } static RGL_Fixed RGL_GetFixedD(double x) { return (RGL_Fixed)(x * RGL_SUBPIXEL_SCALE); } static int RGL_FixedToInt(RGL_Fixed x) { return x >> RGL_SUBPIXEL_SHIFT; } static RGL_Fixed RGL_FixedMul(RGL_Fixed a, RGL_Fixed b) { return (RGL_Fixed)(((long int)a * b) >> RGL_SUBPIXEL_SHIFT); } /* Graphics */ typedef unsigned int RGL_Color; #define RGL_COLOR(a, r, g, b) \ ((RGL_Color)((a << 24) | (r << 16) | (g << 8) | b)) typedef struct { unsigned int width, height; unsigned int *data; } RGL_Buffer; typedef struct { RGL_Color color; unsigned int x, y, width, height; } RGL_Rectangle; typedef struct { RGL_Fixed x, y; } RGL_Point; typedef enum { PathStroke, PathFill } RGL_PathVerb; typedef struct { RGL_PathVerb verb; unsigned int size; RGL_Color color; } RGL_PathHeader; typedef enum { Rect, Path, } RGL_CommandType; typedef struct { RGL_CommandType type; union { RGL_Rectangle rect; RGL_PathHeader path; } data; } RGL_Command; typedef struct { RGL_Arena arena; unsigned int size; RGL_Command *commands; } RGL_CommandQueue; typedef struct { RGL_Color color; RGL_CommandQueue queue; RGL_Command *current; } RGL_Context; void RGL_Rect(RGL_Context *ctx, unsigned int x, unsigned int y, unsigned int width, unsigned int height); void RGL_BeginPath(RGL_Context *ctx, RGL_PathVerb verb); void RGL_PathMoveTo(RGL_Context *ctx, int x, int y); void RGL_EndPath(RGL_Context *ctx); void RGL_DrawRect(RGL_Buffer *buf, RGL_Command *cmd); void RGL_DrawStroke(RGL_Buffer *buf, RGL_PathHeader *path, RGL_Point *points); void RGL_DrawPath(RGL_Buffer *buf, RGL_PathHeader *path, RGL_Point *points); void RGL_Draw(RGL_Context *ctx, RGL_Buffer *buf); #endif