104 #define PNTR_IMPLEMENTATION
111 #define PNTR_PIXELFORMAT_RGBA
118 #define PNTR_PIXELFORMAT_ARGB
125 #define PNTR_ENABLE_DEFAULT_FONT
133 #define PNTR_ENABLE_TTF
142 #define PNTR_ENABLE_UTF8
153 #define PNTR_SAVE_IMAGE_TO_MEMORY
164 #define PNTR_LOAD_IMAGE_FROM_MEMORY
169 #define PNTR_ENABLE_MATH
177 #define PNTR_LOAD_FILE
185 #define PNTR_SAVE_FILE
198 #define PNTR_STB_IMAGE
211 #define PNTR_CUTE_PNG
218 #define PNTR_NO_ALPHABLEND
226 #define PNTR_NO_STDIO
233 #define PNTR_NO_LOAD_IMAGE
240 #define PNTR_NO_SAVE_IMAGE
245 #define PNTR_NO_CUTE_PNG_IMPLEMENTATION
250 #define PNTR_NO_STB_IMAGE_WRITE_IMPLEMENTATION
255 #define PNTR_NO_STB_IMAGE_IMPLEMENTATION
260 #define PNTR_NO_STB_TRUETYPE_IMPLEMENTATION
279#if !defined(PNTR_PIXELFORMAT_RGBA) && !defined(PNTR_PIXELFORMAT_ARGB)
280 #define PNTR_PIXELFORMAT_RGBA
282#if defined(PNTR_PIXELFORMAT_RGBA) && defined(PNTR_PIXELFORMAT_ARGB)
283 #undef PNTR_PIXELFORMAT_ARGB
286#ifdef PNTR_PIXELFORMAT
287 #undef PNTR_PIXELFORMAT
289#ifdef PNTR_PIXELFORMAT_RGBA
298 #define PNTR_PIXELFORMAT PNTR_PIXELFORMAT_RGBA8888
299#elif defined(PNTR_PIXELFORMAT_ARGB)
300 #define PNTR_PIXELFORMAT PNTR_PIXELFORMAT_ARGB8888
304 #if defined(__cplusplus)
305 #define PNTR_CLITERAL(type) type
318 #define PNTR_CLITERAL(type) (type)
333typedef union pntr_color {
347 struct pntr_color_rgba_t {
348 #if defined(PNTR_PIXELFORMAT_RGBA)
353 #elif defined(PNTR_PIXELFORMAT_ARGB)
365typedef struct pntr_rectangle {
378typedef struct pntr_image {
404typedef struct pntr_vector {
418typedef struct pntr_font {
420 pntr_rectangle* srcRects;
421 pntr_rectangle* glyphRects;
430typedef enum pntr_pixelformat {
431 PNTR_PIXELFORMAT_RGBA8888 = 0,
432 PNTR_PIXELFORMAT_ARGB8888,
433 PNTR_PIXELFORMAT_GRAYSCALE
439typedef enum pntr_filter {
440 PNTR_FILTER_NEARESTNEIGHBOR = 0,
450typedef enum pntr_error {
452 PNTR_ERROR_INVALID_ARGS = -1,
453 PNTR_ERROR_NO_MEMORY = -2,
454 PNTR_ERROR_NOT_SUPPORTED = -3,
455 PNTR_ERROR_FAILED_TO_OPEN = -4,
456 PNTR_ERROR_FAILED_TO_WRITE = -5,
457 PNTR_ERROR_UNKNOWN = -6
463typedef enum pntr_image_type {
464 PNTR_IMAGE_TYPE_UNKNOWN = 0,
486PNTR_API void pntr_draw_point_vec(pntr_image* dst, pntr_vector* point, pntr_color color);
487PNTR_API void pntr_draw_points(pntr_image* dst, pntr_vector* points,
int pointsCount, pntr_color color);
488PNTR_API void pntr_draw_line(pntr_image* dst,
int startPosX,
int startPosY,
int endPosX,
int endPosY, pntr_color color);
489PNTR_API void pntr_draw_line_curve(pntr_image* dst, pntr_vector point1, pntr_vector point2, pntr_vector point3, pntr_vector point4,
int segments, pntr_color color);
490PNTR_API void pntr_draw_line_vec(pntr_image* dst, pntr_vector start, pntr_vector end, pntr_color color);
497PNTR_API void pntr_draw_rectangle_gradient(pntr_image* dst,
int x,
int y,
int width,
int height, pntr_color topLeft, pntr_color topRight, pntr_color bottomLeft, pntr_color bottomRight);
498PNTR_API void pntr_draw_rectangle_gradient_rec(pntr_image* dst, pntr_rectangle rect, pntr_color topLeft, pntr_color topRight, pntr_color bottomLeft, pntr_color bottomRight);
507PNTR_API void pntr_draw_polygon(pntr_image* dst, pntr_vector* points,
int numPoints, pntr_color color);
508PNTR_API void pntr_draw_polygon_fill(pntr_image* dst, pntr_vector* points,
int numPoints, pntr_color color);
509PNTR_API void pntr_draw_polyline(pntr_image* dst, pntr_vector* points,
int numPoints, pntr_color color);
510PNTR_API void pntr_draw_arc(pntr_image* dst,
int centerX,
int centerY,
float radius,
float startAngle,
float endAngle,
int segments, pntr_color color);
511PNTR_API void pntr_draw_arc_fill(pntr_image* dst,
int centerX,
int centerY,
float radius,
float startAngle,
float endAngle,
int segments, pntr_color color);
512PNTR_API void pntr_draw_rectangle_rounded(pntr_image* dst,
int x,
int y,
int width,
int height,
int topLeftRadius,
int topRightRadius,
int bottomLeftRadius,
int bottomRightRadius, pntr_color color);
513PNTR_API void pntr_draw_rectangle_rounded_fill(pntr_image* dst,
int x,
int y,
int width,
int height,
int cornerRadius, pntr_color color);
518PNTR_API void pntr_draw_image_rotated(pntr_image* dst, pntr_image* src,
int posX,
int posY,
float degrees,
float offsetX,
float offsetY, pntr_filter filter);
519PNTR_API void pntr_draw_image_rotated_rec(pntr_image* dst, pntr_image* src, pntr_rectangle srcRect,
int posX,
int posY,
float degrees,
float offsetX,
float offsetY, pntr_filter filter);
520PNTR_API void pntr_draw_image_flipped(pntr_image* dst, pntr_image* src,
int posX,
int posY,
bool flipHorizontal,
bool flipVertical,
bool flipDiagonal);
521PNTR_API void pntr_draw_image_flipped_rec(pntr_image* dst, pntr_image* src, pntr_rectangle srcRec,
int posX,
int posY,
bool flipHorizontal,
bool flipVertical,
bool flipDiagonal);
522PNTR_API void pntr_draw_image_scaled(pntr_image* dst, pntr_image* src,
int posX,
int posY,
float scaleX,
float scaleY,
float offsetX,
float offsetY, pntr_filter filter);
523PNTR_API void pntr_draw_image_scaled_rec(pntr_image* dst, pntr_image* src, pntr_rectangle srcRect,
int posX,
int posY,
float scaleX,
float scaleY,
float offsetX,
float offsetY, pntr_filter filter);
524PNTR_API void pntr_draw_text(pntr_image* dst, pntr_font* font,
const char* text,
int posX,
int posY, pntr_color tint);
525PNTR_API void pntr_draw_text_len(pntr_image* dst, pntr_font* font,
const char* text,
int textLength,
int posX,
int posY, pntr_color tint);
527#ifdef PNTR_ENABLE_VARGS
528PNTR_API void pntr_draw_text_ex(pntr_image* dst, pntr_font* font,
int posX,
int posY, pntr_color tint,
int maxlen,
const char* text, ...);
532PNTR_API unsigned char pntr_color_r(pntr_color color);
533PNTR_API unsigned char pntr_color_g(pntr_color color);
534PNTR_API unsigned char pntr_color_b(pntr_color color);
535PNTR_API unsigned char pntr_color_a(pntr_color color);
536PNTR_API void pntr_color_set_r(pntr_color* color,
unsigned char r);
537PNTR_API void pntr_color_set_g(pntr_color* color,
unsigned char g);
538PNTR_API void pntr_color_set_b(pntr_color* color,
unsigned char b);
539PNTR_API void pntr_color_set_a(pntr_color* color,
unsigned char a);
550PNTR_API const char* pntr_get_error(
void);
551PNTR_API pntr_error pntr_get_error_code(
void);
573PNTR_API pntr_font* pntr_load_font_tty_from_memory(
const unsigned char* fileData,
unsigned int dataSize,
int glyphWidth,
int glyphHeight,
const char* characters);
574PNTR_API pntr_font* pntr_load_font_tty_from_image(pntr_image* image,
int glyphWidth,
int glyphHeight,
const char* characters);
594PNTR_API pntr_image*
pntr_gen_image_gradient(
int width,
int height, pntr_color topLeft, pntr_color topRight, pntr_color bottomLeft, pntr_color bottomRight);
601PNTR_API void pntr_draw_line_thick(pntr_image* dst,
int startPosX,
int startPosY,
int endPosX,
int endPosY,
int thickness, pntr_color color);
602PNTR_API void pntr_draw_line_thick_vec(pntr_image* dst, pntr_vector start, pntr_vector end,
int thickness, pntr_color color);
603PNTR_API void pntr_draw_rectangle_thick(pntr_image* dst,
int posX,
int posY,
int width,
int height,
int thickness, pntr_color color);
604PNTR_API void pntr_draw_rectangle_thick_rec(pntr_image* dst, pntr_rectangle rect,
int thickness, pntr_color color);
609PNTR_API void pntr_draw_polygon_thick(pntr_image* dst, pntr_vector* points,
int numPoints,
int thickness, pntr_color color);
610PNTR_API void pntr_draw_polyline_thick(pntr_image* dst, pntr_vector* points,
int numPoints,
int thickness, pntr_color color);
611PNTR_API void pntr_draw_arc_thick(pntr_image* dst,
int centerX,
int centerY,
float radius,
float startAngle,
float endAngle,
int segments,
int thickness, pntr_color color);
612PNTR_API void pntr_draw_rectangle_thick_rounded(pntr_image* dst,
int x,
int y,
int width,
int height,
int topLeftRadius,
int topRightRadius,
int bottomLeftRadius,
int bottomRightRadius,
int thickness, pntr_color color);
613PNTR_API void pntr_draw_line_vertical_thick(pntr_image* dst,
int posX,
int posY,
int height,
int thickness, pntr_color color);
614PNTR_API void pntr_draw_line_horizontal_thick(pntr_image* dst,
int posX,
int posY,
int width,
int thickness, pntr_color color);
615PNTR_API void pntr_draw_line_curve_thick(pntr_image* dst, pntr_vector point1, pntr_vector point2, pntr_vector point3, pntr_vector point4,
int segments,
int thickness, pntr_color color);
630#ifndef PNTR_LIGHTGRAY
634#define PNTR_LIGHTGRAY pntr_new_color(200, 200, 200, 255)
640#define PNTR_GRAY pntr_new_color(130, 130, 130, 255)
646#define PNTR_DARKGRAY pntr_new_color(80, 80, 80, 255)
652#define PNTR_YELLOW pntr_new_color(253, 249, 0, 255)
658#define PNTR_GOLD pntr_new_color(255, 203, 0, 255)
664#define PNTR_ORANGE pntr_new_color(255, 161, 0, 255)
670#define PNTR_PINK pntr_new_color(255, 109, 194, 255)
676#define PNTR_RED pntr_new_color(230, 41, 55, 255)
682#define PNTR_MAROON pntr_new_color(190, 33, 55, 255)
688#define PNTR_GREEN pntr_new_color(0, 228, 48, 255)
694#define PNTR_LIME pntr_new_color(0, 158, 47, 255)
696#ifndef PNTR_DARKGREEN
700#define PNTR_DARKGREEN pntr_new_color(0, 117, 44, 255)
706#define PNTR_SKYBLUE pntr_new_color(102, 191, 255, 255)
712#define PNTR_BLUE pntr_new_color(0, 121, 241, 255)
718#define PNTR_DARKBLUE pntr_new_color(0, 82, 172, 255)
724#define PNTR_PURPLE pntr_new_color(200, 122, 255, 255)
730#define PNTR_VIOLET pntr_new_color(135, 60, 190, 255)
732#ifndef PNTR_DARKPURPLE
736#define PNTR_DARKPURPLE pntr_new_color(112, 31, 126, 255)
742#define PNTR_BEIGE pntr_new_color(211, 176, 131, 255)
748#define PNTR_BROWN pntr_new_color(127, 106, 79, 255)
750#ifndef PNTR_DARKBROWN
754#define PNTR_DARKBROWN pntr_new_color(76, 63, 47, 255)
760#define PNTR_WHITE pntr_new_color(255, 255, 255, 255)
763#ifndef PNTR_WHITE_VALUE
772#define PNTR_WHITE_VALUE 4294967295
779#define PNTR_BLACK pntr_new_color(0, 0, 0, 255)
785#define PNTR_BLANK pntr_new_color(0, 0, 0, 0)
791#define PNTR_MAGENTA pntr_new_color(255, 0, 255, 255)
797#define PNTR_RAYWHITE pntr_new_color(245, 245, 245, 255)
806#ifdef PNTR_IMPLEMENTATION
807#ifndef PNTR_IMPLEMENTATION_ONCE
808#define PNTR_IMPLEMENTATION_ONCE
810#if defined(PNTR_ENABLE_UTF8) && !defined(_DOXYGEN_)
811 #include "external/utf8.h"
812 #define PNTR_STRSTR utf8str
813 #define PNTR_STRCHR utf8chr
814 #define PNTR_STRLEN utf8len
815 #define PNTR_STRSIZE utf8size
816 #define PNTR_STRCODEPOINT utf8codepoint
817 typedef utf8_int32_t pntr_codepoint_t;
826 typedef char pntr_codepoint_t;
849 #define PNTR_MALLOC(size) malloc(size)
862 #define PNTR_FREE(ptr) free(ptr)
877 #define PNTR_REALLOC(ptr, new_size) realloc(ptr, new_size)
891 #define PNTR_MEMCPY(dest, src, n) memcpy(dest, src, (n))
899 #define PNTR_MEMSET(str, c, n) memset((str), (c), (n))
925 #define PNTR_STRSTR strstr
937 #define PNTR_STRCHR strchr
949 #define PNTR_STRLEN strlen
961 #define PNTR_STRSIZE(text) ((PNTR_STRLEN(text) + (size_t)1))
964#ifndef PNTR_STRCODEPOINT
978 char* pntr_strcodepoint(
const char * str,
char* out_codepoint) {
983 *out_codepoint = str[0];
984 return (
char*)(str + 1);
995 #define PNTR_STRCODEPOINT pntr_strcodepoint
1013 #define PNTR_PI 3.1415926535897932f
1024 #define PNTR_DEG2RAD 0.017453293f
1027#if !defined(PNTR_ENABLE_MATH) || defined(_DOXYGEN_)
1034 float _pntr_sinf(
float x) {
1035 static const float a0 = +1.91059300966915117e-31f;
1036 static const float a1 = +1.00086760103908896f;
1037 static const float a2 = -1.21276126894734565e-2f;
1038 static const float a3 = -1.38078780785773762e-1f;
1039 static const float a4 = -2.67353392911981221e-2f;
1040 static const float a5 = +2.08026600266304389e-2f;
1041 static const float a6 = -3.03996055049204407e-3f;
1042 static const float a7 = +1.38235642404333740e-4f;
1043 return a0 + x*(a1 + x*(a2 + x*(a3 + x*(a4 + x*(a5 + x*(a6 + x*a7))))));
1056 #define PNTR_SINF(value) _pntr_sinf(value)
1065 float _pntr_cosf(
float x) {
1066 static const float a0 = 9.9995999154986614e-1f;
1067 static const float a1 = 1.2548995793001028e-3f;
1068 static const float a2 = -5.0648546280678015e-1f;
1069 static const float a3 = 1.2942246466519995e-2f;
1070 static const float a4 = 2.8668384702547972e-2f;
1071 static const float a5 = 7.3726485210586547e-3f;
1072 static const float a6 = -3.8510875386947414e-3f;
1073 static const float a7 = 4.7196604604366623e-4f;
1074 static const float a8 = -1.8776444013090451e-5f;
1075 return a0 + x*(a1 + x*(a2 + x*(a3 + x*(a4 + x*(a5 + x*(a6 + x*(a7 + x*a8)))))));
1088 #define PNTR_COSF(value) _pntr_cosf(value)
1097 float _pntr_ceilf(
float x) {
1100 return (x > i) ? (float)i + 1.0f : (float)i;
1103 float r = x - (float)t;
1104 return (r > 0.0f) ? (float)t + 1.0f: (float)t;
1117 #define PNTR_CEILF(x) _pntr_ceilf(x)
1130 #define PNTR_FABSF(x) (((x) < 0) ? -(x) : (x))
1143 #define PNTR_FLOORF(x) (float)(((int)(x)) - (((x) < 0.0f) ? 1 : 0))
1156 #define PNTR_FMODF(dividend, divisor) ((divisor) == 0.0f ? 0.0f : (dividend) - ((int)((dividend) / (divisor))) * (divisor))
1161 #define PNTR_SINF sinf
1166 #define PNTR_COSF cosf
1171 #define PNTR_CEILF ceilf
1176 #define PNTR_FABSF fabsf
1181 #define PNTR_FLOORF floorf
1186 #define PNTR_SQRTF sqrtf
1191 #define PNTR_FMODF fmodf
1204 #define PNTR_MAX(a, b) ((a) > (b) ? (a) : (b))
1216 #define PNTR_MIN(a, b) ((a) < (b) ? (a) : (b))
1224#ifdef PNTR_ENABLE_TTF
1225 #ifdef PNTR_NO_STB_TRUETYPE_IMPLEMENTATION
1226 #ifdef STB_TRUETYPE_IMPLEMENTATION
1227 #undef STB_TRUETYPE_IMPLEMENTATION
1231 #ifndef STBTT_ifloor
1232 #define STBTT_ifloor(x) ((int)PNTR_FLOORF(x))
1236 #define STBTT_iceil(x) ((int)PNTR_CEILF(x))
1240 #define STBTT_fmod(x, y) PNTR_FMODF((x), (y))
1244 #define STBTT_cos(x) PNTR_COSF((float)(x))
1248 #define STBTT_fabs(x) PNTR_FABSF(x)
1251 #ifndef PNTR_ENABLE_MATH
1253 float _pntr_sqrtf(
float number) {
1254 float guess = number / 2.0f;
1255 float epsilon = 1e-6f;
1257 float next_guess = 0.5f * (guess + number / guess);
1258 if (
PNTR_FABSF(next_guess - guess) < epsilon) {
1264 #define STBTT_sqrt(x) _pntr_sqrtf(x)
1268 float _pntr_pow(
float base,
float exponent) {
1269 float result = 1.0f;
1270 if (exponent >= 0) {
1271 for (
int i = 0; i < exponent; i++) {
1275 for (
int i = 0; i > exponent; i--) {
1281 #define STBTT_pow(x, y) _pntr_pow((x), (y))
1285 float _pntr_acos(
float x) {
1286 float negate = (float)(x < 0);
1288 float ret = -0.0187293f;
1290 ret = ret + 0.0742610f;
1292 ret = ret - 0.2121144f;
1294 ret = ret + 1.5707288f;
1295 ret = ret * STBTT_sqrt(1.0f - x);
1296 ret = ret - 2 * negate * ret;
1297 return negate * PNTR_PI + ret;
1299 #define STBTT_acos(x) _pntr_acos((x))
1303 #define STBTT_sqrt(x) sqrt(x)
1306 #define STBTT_pow(x, y) pow(x, y)
1309 #define STBTT_acos(x) acos(x)
1313 #ifndef STBTT_malloc
1314 #define STBTT_malloc(x,u) ((void)(u), PNTR_MALLOC(x))
1318 #define STBTT_free(x,u) ((void)(u), PNTR_FREE(x))
1321 #ifndef STBTT_assert
1322 #define STBTT_assert(x) ((void)(0))
1325 #ifndef STBTT_strlen
1326 #define STBTT_strlen(x) PNTR_STRLEN(x)
1329 #ifndef STBTT_memcpy
1330 #define STBTT_memcpy PNTR_MEMCPY
1333 #ifndef STBTT_memset
1334 #define STBTT_memset PNTR_MEMSET
1337 #define STB_TRUETYPE_IMPLEMENTATION
1340 #if defined(__GNUC__) || defined(__clang__)
1341 #pragma GCC diagnostic push
1342 #pragma GCC diagnostic ignored "-Wpragmas"
1343 #pragma GCC diagnostic ignored "-Wunknown-pragmas"
1344 #pragma GCC diagnostic ignored "-Wsign-conversion"
1345 #pragma GCC diagnostic ignored "-Wconversion"
1348 #include "external/stb_truetype.h"
1349 #define PNTR_NO_STB_TRUETYPE_IMPLEMENTATION
1351 #if defined(__GNUC__) || defined(__clang__)
1352 #pragma GCC diagnostic pop
1356#ifdef PNTR_ENABLE_VARGS
1372#define PNTR_PIXEL(image, x, y) image->data[(y) * (image->pitch >> 2) + (x)]
1386#ifndef PNTR_NEW_COLOR
1387 #if defined(PNTR_PIXELFORMAT_RGBA)
1388 #define PNTR_NEW_COLOR(red, green, blue, alpha) PNTR_CLITERAL(pntr_color) { \
1396 #elif defined(PNTR_PIXELFORMAT_ARGB)
1397 #define PNTR_NEW_COLOR(red, green, blue, alpha) PNTR_CLITERAL(pntr_color) { \
1418pntr_error _pntr_error;
1420PNTR_API const char* pntr_get_error(
void) {
1421 switch (_pntr_error) {
1422 case PNTR_ERROR_NONE:
return NULL;
1423 case PNTR_ERROR_INVALID_ARGS:
return "Invalid arguments";
1424 case PNTR_ERROR_NO_MEMORY:
return "No memory";
1425 case PNTR_ERROR_NOT_SUPPORTED:
return "Not supported";
1426 case PNTR_ERROR_FAILED_TO_OPEN:
return "Failed to open";
1427 case PNTR_ERROR_FAILED_TO_WRITE:
return "Failed to write";
1428 case PNTR_ERROR_UNKNOWN:
return "Unknown error";
1434PNTR_API pntr_error pntr_get_error_code(
void) {
1446 _pntr_error = error;
1448 #ifdef PNTR_SET_ERROR
1449 PNTR_SET_ERROR(error);
1468 if (width <= 0 || height <= 0) {
1472 pntr_image* image = (pntr_image*)PNTR_MALLOC(
sizeof(pntr_image));
1473 if (image == NULL) {
1477 image->pitch = width * (int)
sizeof(pntr_color);
1478 image->width = width;
1479 image->height = height;
1481 image->subimage =
false;
1482 image->data = (pntr_color*)PNTR_MALLOC((
size_t)(image->pitch * height));
1483 if (image->data == NULL) {
1515 if (image == NULL) {
1520 if (newImage == NULL) {
1525 newImage->clip = image->clip;
1540#ifdef PNTR_NO_ALPHABLEND
1544 if (src.rgba.a == 255) {
1548 #ifndef PNTR_NO_ALPHABLEND
1549 if (src.rgba.a == 0) {
1553 unsigned int alpha = (
unsigned int)src.rgba.a + 1;
1554 unsigned int dstAlpha = (
unsigned int)dst->rgba.a * (256 - alpha);
1555 dst->rgba.a = (
unsigned char)((alpha * 256 + dstAlpha) >> 8);
1557 if (dst->rgba.a > 0) {
1558 dst->rgba.r = (
unsigned char)((((
unsigned int)src.rgba.r * alpha * 256 + (
unsigned int)dst->rgba.r * dstAlpha) / dst->rgba.a) >> 8);
1559 dst->rgba.g = (
unsigned char)((((
unsigned int)src.rgba.g * alpha * 256 + (
unsigned int)dst->rgba.g * dstAlpha) / dst->rgba.a) >> 8);
1560 dst->rgba.b = (
unsigned char)((((
unsigned int)src.rgba.b * alpha * 256 + (
unsigned int)dst->rgba.b * dstAlpha) / dst->rgba.a) >> 8);
1589PNTR_API bool _pntr_rectangle_intersect(
int x,
int y,
int width,
int height,
int destX,
int destY,
int destWidth,
int destHeight, pntr_rectangle *out) {
1590 if (width <= 0 || height <= 0) {
1595 out->width =
PNTR_MIN(x + width, destX + destWidth) - out->x;
1596 if (out->width <= 0) {
1601 out->height =
PNTR_MIN(y + height, destY + destHeight) - out->y;
1602 if (out->height <= 0) {
1626 if (image == NULL) {
1630 pntr_rectangle dstRect;
1631 if (!_pntr_rectangle_intersect(x, y, width, height, 0, 0, image->width, image->height, &dstRect)) {
1635 pntr_image* result =
pntr_new_image(dstRect.width, dstRect.height);
1636 if (result == NULL) {
1640 for (
int destY = 0; destY < dstRect.height; destY++) {
1642 &
PNTR_PIXEL(image, dstRect.x, dstRect.y + destY),
1643 (
size_t)result->pitch);
1666 if (image == NULL) {
1671 pntr_rectangle dstRect;
1672 if (!_pntr_rectangle_intersect(x, y, width, height, 0, 0, image->width, image->height, &dstRect)) {
1677 pntr_image* subimage = (pntr_image*)PNTR_MALLOC(
sizeof(pntr_image));
1678 if (subimage == NULL) {
1682 subimage->pitch = image->pitch;
1683 subimage->width = dstRect.width;
1684 subimage->height = dstRect.height;
1685 subimage->subimage =
true;
1687 subimage->data = &
PNTR_PIXEL(image, dstRect.x, dstRect.y);
1698 if (image == NULL) {
1703 if (!image->subimage && image->data != NULL) {
1704 PNTR_FREE(image->data);
1714 pntr_color *row = &
PNTR_PIXEL(dst, posX, posY);
1715 while (--width >= 0) {
1729 if (image == NULL) {
1734 if (!image->subimage) {
1736 if (color.value == PNTR_WHITE_VALUE) {
1737 PNTR_MEMSET((
void*)image->data, 255, (
size_t)(image->height * image->pitch));
1742 if (color.rgba.a == 0) {
1743 PNTR_MEMSET((
void*)image->data, 0, (
size_t)(image->height * image->pitch));
1752 for (
int y = 1; y < image->height; y++) {
1753 PNTR_MEMCPY(&
PNTR_PIXEL(image, 0, y), image->data, (
size_t)image->pitch);
1780 (
unsigned char)((hexValue >> 24U) & (
unsigned int)0xFF),
1781 (
unsigned char)((hexValue >> 16U) & (
unsigned int)0xFF),
1782 (
unsigned char)((hexValue >> 8U) & (
unsigned int)0xFF),
1783 (
unsigned char)(hexValue & (
unsigned int)0xFF)
1787PNTR_API unsigned char pntr_color_r(pntr_color color) {
1788 return color.rgba.r;
1791PNTR_API unsigned char pntr_color_g(pntr_color color) {
1792 return color.rgba.g;
1795PNTR_API unsigned char pntr_color_b(pntr_color color) {
1796 return color.rgba.b;
1799PNTR_API unsigned char pntr_color_a(pntr_color color) {
1800 return color.rgba.a;
1803PNTR_API void pntr_color_set_r(pntr_color* color,
unsigned char r) {
1807PNTR_API void pntr_color_set_g(pntr_color* color,
unsigned char g) {
1811PNTR_API void pntr_color_set_b(pntr_color* color,
unsigned char b) {
1815PNTR_API void pntr_color_set_a(pntr_color* color,
unsigned char a) {
1830 if ((color.rgba.a == 0) || (dst == NULL) || (x < dst->clip.x) || (x >= dst->clip.x + dst->clip.width) || (y < dst->clip.y) || (y >= dst->clip.y + dst->clip.height)) {
1837PNTR_API void pntr_draw_point_vec(pntr_image* dst, pntr_vector* point, pntr_color color) {
1838 if (point != NULL) {
1843PNTR_API void pntr_draw_points(pntr_image* dst, pntr_vector* points,
int pointsCount, pntr_color color) {
1844 if (dst == NULL || color.rgba.a == 0 || points == NULL || pointsCount <= 0) {
1848 for (
int i = 0; i < pointsCount; i++) {
1849 if (points[i].x >= dst->clip.x && points[i].x < dst->clip.x + dst->clip.width && points[i].y >= dst->clip.y && points[i].y < dst->clip.y + dst->clip.height) {
1864 if (dst == NULL || color.rgba.a == 0) {
1868 int changeInX = (endPosX - startPosX);
1869 int absChangeInX = (changeInX < 0) ? -changeInX : changeInX;
1870 int changeInY = (endPosY - startPosY);
1871 int absChangeInY = (changeInY < 0) ? -changeInY : changeInY;
1874 if (startPosX == endPosX) {
1879 if (startPosY == endPosY) {
1884 int startU, startV, endU, stepV;
1886 int reversedXY = (absChangeInY < absChangeInX);
1889 A = 2 * absChangeInY;
1890 B = A - 2 * absChangeInX;
1891 P = A - absChangeInX;
1893 if (changeInX > 0) {
1906 changeInX = -changeInX;
1907 changeInY = -changeInY;
1910 stepV = (changeInY < 0) ? -1 : 1;
1915 A = 2 * absChangeInX;
1916 B = A - 2 * absChangeInY;
1917 P = A - absChangeInY;
1919 if (changeInY > 0) {
1929 changeInX = -changeInX;
1930 changeInY = -changeInY;
1933 stepV = (changeInX < 0) ? -1 : 1;
1938 for (
int u = startU + 1, v = startV; u <= endU; u++) {
1960 if (thickness < 1) {
1963 if (thickness == 1) {
1964 pntr_draw_line(dst, startPosX, startPosY, endPosX, endPosY, color);
1968 if (dst == NULL || color.rgba.a == 0) {
1972 int changeInX = (endPosX - startPosX);
1973 int absChangeInX = (changeInX < 0) ? -changeInX : changeInX;
1974 int changeInY = (endPosY - startPosY);
1975 int absChangeInY = (changeInY < 0) ? -changeInY : changeInY;
1978 if (startPosX == endPosX) {
1979 pntr_draw_line_vertical_thick(dst, startPosX, (startPosY > endPosY) ? endPosY : startPosY, absChangeInY, thickness, color);
1983 if (startPosY == endPosY) {
1984 pntr_draw_line_horizontal_thick(dst, (startPosX > endPosX) ? endPosX : startPosX, startPosY, absChangeInX, thickness, color);
1988 int startU, startV, endU, stepV;
1990 int reversedXY = (absChangeInY < absChangeInX);
1993 A = 2 * absChangeInY;
1994 B = A - 2 * absChangeInX;
1995 P = A - absChangeInX;
1997 if (changeInX > 0) {
2010 changeInX = -changeInX;
2011 changeInY = -changeInY;
2014 stepV = (changeInY < 0) ? -1 : 1;
2020 A = 2 * absChangeInX;
2021 B = A - 2 * absChangeInY;
2022 P = A - absChangeInY;
2024 if (changeInY > 0) {
2034 changeInX = -changeInX;
2035 changeInY = -changeInY;
2038 stepV = (changeInX < 0) ? -1 : 1;
2045 for (
int u = startU + 1, v = startV; u <= endU; u++) {
2065PNTR_API void pntr_draw_line_curve(pntr_image* dst, pntr_vector point1, pntr_vector point2, pntr_vector point3, pntr_vector point4,
int segments, pntr_color color) {
2066 if (dst == NULL || color.rgba.a == 0 || segments <= 0) {
2070 float t_step = 1.0f / (float)segments;
2071 pntr_vector last = point1;
2072 for (
int i_step = 1; i_step <= segments; ++i_step) {
2073 float t = t_step * (float)i_step;
2075 float w1 = u * u * u;
2076 float w2 = 3 * u * u * t;
2077 float w3 = 3 * u * t * t;
2078 float w4 = t * t * t;
2079 float x = w1 * (float)point1.x + w2 * (
float)point2.x + w3 * (float)point3.x + w4 * (
float)point4.x;
2080 float y = w1 * (float)point1.y + w2 * (
float)point2.y + w3 * (float)point3.y + w4 * (
float)point4.y;
2087PNTR_API void pntr_draw_line_curve_thick(pntr_image* dst, pntr_vector point1, pntr_vector point2, pntr_vector point3, pntr_vector point4,
int segments,
int thickness, pntr_color color) {
2088 if (dst == NULL || color.rgba.a == 0 || segments <= 0) {
2092 float t_step = 1.0f / (float)segments;
2093 pntr_vector last = point1;
2094 for (
int i_step = 1; i_step <= segments; ++i_step) {
2095 float t = t_step * (float)i_step;
2097 float w1 = u * u * u;
2098 float w2 = 3 * u * u * t;
2099 float w3 = 3 * u * t * t;
2100 float w4 = t * t * t;
2101 float x = w1 * (float)point1.x + w2 * (
float)point2.x + w3 * (float)point3.x + w4 * (
float)point4.x;
2102 float y = w1 * (float)point1.y + w2 * (
float)point2.y + w3 * (float)point3.y + w4 * (
float)point4.y;
2109PNTR_API void pntr_draw_polyline(pntr_image* dst, pntr_vector* points,
int numPoints, pntr_color color) {
2110 if (color.rgba.a == 0 || dst == NULL || numPoints <= 0 || points == NULL) {
2114 if (numPoints == 1) {
2115 pntr_draw_point_vec(dst, points, color);
2119 for (
int i = 0; i < numPoints - 1; i++) {
2120 pntr_draw_line_vec(dst, points[i], points[i + 1], color);
2124PNTR_API void pntr_draw_polyline_thick(pntr_image* dst, pntr_vector* points,
int numPoints,
int thickness, pntr_color color) {
2125 if (color.rgba.a == 0 || dst == NULL || numPoints <= 0 || points == NULL) {
2129 if (numPoints == 1) {
2130 pntr_draw_point_vec(dst, points, color);
2134 for (
int i = 0; i < numPoints - 1; i++) {
2135 pntr_draw_line_thick_vec(dst, points[i], points[i + 1], thickness, color);
2154 if (color.rgba.a == 0 || dst == NULL || posY < dst->clip.y || posY >= dst->clip.y + dst->clip.height || posX >= dst->clip.x + dst->clip.width || posX + width < dst->clip.x) {
2158 if (posX < dst->clip.x) {
2159 width += posX - dst->clip.x;
2162 if (posX + width >= dst->clip.x + dst->clip.width) {
2163 width = dst->clip.x + dst->clip.width - posX;
2166 if (color.rgba.a == 255) {
2170 pntr_color *row = &
PNTR_PIXEL(dst, posX, posY);
2171 while (--width >= 0) {
2177PNTR_API void pntr_draw_line_horizontal_thick(pntr_image* dst,
int posX,
int posY,
int width,
int thickness, pntr_color color) {
2178 if (thickness == 0) {
2181 if (thickness == 1) {
2206 if (color.rgba.a == 0 || dst == NULL || posX < dst->clip.x || posX >= dst->clip.x + dst->clip.width || posY >= dst->clip.y + dst->clip.height || posY + height < dst->clip.y) {
2210 if (posY < dst->clip.y) {
2211 height += posY - dst->clip.y;
2214 if (posY + height >= dst->clip.y + dst->clip.height) {
2215 height = dst->clip.y + dst->clip.height - posY;
2218 if (color.rgba.a == 255) {
2219 for (
int y = 0; y < height; y++) {
2224 for (
int y = 0; y < height; y++) {
2230PNTR_API void pntr_draw_line_vertical_thick(pntr_image* dst,
int posX,
int posY,
int height,
int thickness, pntr_color color) {
2231 if (thickness == 0) {
2234 if (thickness == 1) {
2268 if (color.rgba.a == 0 || dst == NULL || width <= 0 || height <= 0) {
2278PNTR_API void pntr_draw_rectangle_thick(pntr_image* dst,
int posX,
int posY,
int width,
int height,
int thickness, pntr_color color) {
2279 for (
int i = 0; i < thickness; i++) {
2284PNTR_API void pntr_draw_rectangle_thick_rec(pntr_image* dst, pntr_rectangle rect,
int thickness, pntr_color color) {
2285 pntr_draw_rectangle_thick(dst, rect.x, rect.y, rect.width, rect.height, thickness, color);
2314 if (color.rgba.a == 0 || dst == NULL) {
2318 if (!_pntr_rectangle_intersect(rect.x, rect.y, rect.width, rect.height, dst->clip.x, dst->clip.y, dst->clip.width, dst->clip.height, &rect)) {
2323 if (color.rgba.a == 255) {
2326 pntr_color* srcPixel = &
PNTR_PIXEL(dst, rect.x, rect.y);
2327 for (
int y = rect.y + 1; y < rect.y + rect.height; y++) {
2328 PNTR_MEMCPY(&
PNTR_PIXEL(dst, rect.x, y), srcPixel, (
size_t)rect.width *
sizeof(pntr_color));
2332 for (
int y = 0; y < rect.height; y++) {
2333 pntr_color* col = &
PNTR_PIXEL(dst, rect.x, rect.y + y);
2334 for (
int x = 0; x < rect.width; x++) {
2341PNTR_API void pntr_draw_rectangle_gradient_rec(pntr_image* dst, pntr_rectangle rect, pntr_color topLeft, pntr_color topRight, pntr_color bottomLeft, pntr_color bottomRight) {
2346 pntr_rectangle dstRect;
2347 if (!_pntr_rectangle_intersect(rect.x, rect.y, rect.width, rect.height, dst->clip.x, dst->clip.y, dst->clip.width, dst->clip.height, &dstRect)) {
2352 if (rect.width == 0 || rect.height == 0) {
2356 float width = (float)rect.width;
2357 float height = (float)rect.height;
2358 for (
int x = dstRect.x; x < dstRect.x + dstRect.width; x++) {
2359 float factorX = (float)(x - rect.x) / width;
2360 for (
int y = dstRect.y; y < dstRect.y + dstRect.height; y++) {
2362 topLeft, bottomLeft,
2363 topRight, bottomRight,
2365 (
float)(y - rect.y) / height
2371PNTR_API void pntr_draw_rectangle_gradient(pntr_image* dst,
int x,
int y,
int width,
int height, pntr_color topLeft, pntr_color topRight, pntr_color bottomLeft, pntr_color bottomRight) {
2372 pntr_draw_rectangle_gradient_rec(dst, PNTR_CLITERAL(pntr_rectangle) {x, y, width, height}, topLeft, topRight, bottomLeft, bottomRight);
2392 if (dst == NULL || color.rgba.a == 0) {
2410 if (centerX + radius < dst->clip.x || centerY + radius < dst->clip.y || centerX - radius > dst->clip.x + dst->clip.width || centerY - radius > dst->clip.y + dst->clip.height) {
2414 int largestX = radius;
2415 int r2 = radius * radius;
2416 for (
int y = 0; y <= radius; ++y) {
2418 for (
int x = largestX; x >= 0; --x) {
2419 if (x * x + y2 <= r2) {
2462 if (dst == NULL || color.rgba.a == 0 || radius == 0 || centerX + radius < dst->clip.x || centerX - radius >= dst->clip.x + dst->clip.width || centerY + radius < dst->clip.y || centerY - radius >= dst->clip.y + dst->clip.height) {
2466 int largestX = radius;
2467 int r2 = radius * radius;
2468 for (
int y = 0; y <= radius; ++y) {
2470 for (
int x = largestX; x >= 0; --x) {
2471 if (x * x + y2 <= r2) {
2494 if (thickness < 1) {
2497 if (thickness == 1) {
2501 if (dst == NULL || color.rgba.a == 0) {
2510 if (centerX + radius < dst->clip.x || centerY + radius < dst->clip.y || centerX - radius > dst->clip.x + dst->clip.width || centerY - radius > dst->clip.y + dst->clip.height) {
2514 int largestX = radius;
2515 int r2 = radius * radius;
2516 for (
int y = 0; y <= radius; ++y) {
2518 for (
int x = largestX; x >= 0; --x) {
2519 if (x * x + y2 <= r2) {
2548 if (dst == NULL || radiusX == 0 || radiusY == 0 || color.rgba.a == 0) {
2560 int radiusXSquared = radiusX * radiusX;
2561 int radiusXSquared2 = radiusXSquared * 2;
2562 int radiusYSquared = radiusY * radiusY;
2563 int radiusYSquared2 = radiusYSquared * 2;
2564 int error = radiusYSquared - radiusXSquared * radiusY;
2566 while (radiusY >= 0) {
2574 error += radiusYSquared2 * x + radiusYSquared;
2578 error -= radiusXSquared2 * radiusY - radiusXSquared;
2605 if (dst == NULL || radiusX == 0 || radiusY == 0 || color.rgba.a == 0 || centerX + radiusX < dst->clip.x || centerX - radiusX > dst->clip.x + dst->clip.width || centerY + radiusY < dst->clip.y || centerY - radiusY > dst->clip.y + dst->clip.height) {
2610 int radiusXSquared = radiusX * radiusX;
2611 int radiusXSquared2 = radiusXSquared * 2;
2612 int radiusYSquared = radiusY * radiusY;
2613 int radiusYSquared2 = radiusYSquared * 2;
2614 int error = radiusYSquared - radiusXSquared * radiusY;
2616 while (radiusY >= 0) {
2624 error += radiusYSquared2 * x + radiusYSquared;
2628 error -= radiusXSquared2 * radiusY - radiusXSquared;
2646 if (thickness < 1) {
2649 if (thickness == 1) {
2653 if (dst == NULL || radiusX == 0 || radiusY == 0 || color.rgba.a == 0) {
2665 int radiusXSquared = radiusX * radiusX;
2666 int radiusXSquared2 = radiusXSquared * 2;
2667 int radiusYSquared = radiusY * radiusY;
2668 int radiusYSquared2 = radiusYSquared * 2;
2669 int error = radiusYSquared - radiusXSquared * radiusY;
2671 while (radiusY >= 0) {
2679 error += radiusYSquared2 * x + radiusYSquared;
2683 error -= radiusXSquared2 * radiusY - radiusXSquared;
2698 pntr_draw_triangle(dst, point1.x, point1.y, point2.x, point2.y, point3.x, point3.y, color);
2769 PNTR_CLITERAL(pntr_vector) { .x = x1, .y = y1 },
2770 PNTR_CLITERAL(pntr_vector) { .x = x2, .y = y2 },
2771 PNTR_CLITERAL(pntr_vector) { .x = x3, .y = y3 },
2776PNTR_API void pntr_draw_line_vec(pntr_image* dst, pntr_vector start, pntr_vector end, pntr_color color) {
2780PNTR_API void pntr_draw_line_thick_vec(pntr_image* dst, pntr_vector start, pntr_vector end,
int thickness, pntr_color color) {
2784PNTR_API void pntr_draw_polygon(pntr_image* dst, pntr_vector* points,
int numPoints, pntr_color color) {
2785 if (dst == NULL || color.rgba.a == 0 || numPoints <= 0 || points == NULL) {
2790 for (
int i = 0; i < numPoints; i++) {
2791 if (i < numPoints - 1) {
2792 nextPointIndex = i + 1;
2798 pntr_draw_line(dst, points[i].x, points[i].y, points[nextPointIndex].x, points[nextPointIndex].y, color);
2802PNTR_API void pntr_draw_polygon_thick(pntr_image* dst, pntr_vector* points,
int numPoints,
int thickness, pntr_color color) {
2803 if (dst == NULL || color.rgba.a == 0 || numPoints <= 0 || points == NULL) {
2808 for (
int i = 0; i < numPoints; i++) {
2809 if (i < numPoints - 1) {
2810 nextPointIndex = i + 1;
2816 pntr_draw_line_thick(dst, points[i].x, points[i].y, points[nextPointIndex].x, points[nextPointIndex].y, thickness, color);
2820PNTR_API void pntr_draw_polygon_fill(pntr_image* dst, pntr_vector* points,
int numPoints, pntr_color color) {
2821 if (dst == NULL || points == NULL || numPoints <= 0 || color.rgba.a == 0) {
2827 int left = points[0].x, top = points[0].y, bottom = points[0].y, right = points[0].x;
2828 int nodes, pixelX, pixelY, j, swap;
2829 int* nodeX = (
int*)PNTR_MALLOC(
sizeof(
int) * (size_t)numPoints);
2830 if (nodeX == NULL) {
2835 for (i = 0; i < numPoints; i++) {
2836 if (left > points[i].x)
2838 if (right < points[i].x)
2839 right = points[i].x;
2840 if (top > points[i].y)
2842 if (bottom < points[i].y)
2843 bottom = points[i].y;
2850 for (pixelY = top; pixelY < bottom; pixelY ++) {
2853 for (i = 0; i < numPoints; i++) {
2854 if (((points[i].y < pixelY) && (points[j].y >= pixelY)) ||
2855 ((points[j].y < pixelY) && (points[i].y >= pixelY))) {
2856 nodeX[nodes++]= (int)((
float)points[i].x
2857 + ((float)pixelY - (
float)points[i].y) / ((
float)points[j].y - (float)points[i].y)
2858 * ((float)points[j].x - (
float)points[i].x));
2864 while (i < nodes - 1) {
2865 if (nodeX[i] > nodeX[i+1]) {
2867 nodeX[i] = nodeX[i+1];
2873 for (i = 0; i < nodes; i += 2) {
2874 if (nodeX[i+0] >= right)
break;
2875 if (nodeX[i+1] > left) {
2876 if (nodeX[i+0] < left) nodeX[i+0] = left ;
2877 if (nodeX[i+1] > right) nodeX[i+1] = right;
2878 for (pixelX = nodeX[i]; pixelX < nodeX[i + 1]; pixelX++)
2897 pntr_vector points[3];
2901 pntr_draw_polygon_fill(dst, points, 3, color);
2904PNTR_API void pntr_draw_arc(pntr_image* dst,
int centerX,
int centerY,
float radius,
float startAngle,
float endAngle,
int segments, pntr_color color) {
2905 if (radius <= 0.0f) {
2909 if (segments <= 0) {
2913 float startAngleRad = startAngle * PNTR_PI / 180.0f;
2914 float endAngleRad = endAngle * PNTR_PI / 180.0f;
2917 float stepAngle = (endAngleRad - startAngleRad) / (
float)(segments);
2935 for (
int i = 0; i < segments; i++) {
2936 endAngleRad = startAngleRad + (float)i * stepAngle;
2938 centerX + (
int)(radius *
PNTR_COSF(endAngleRad)),
2939 centerY + (
int)(radius *
PNTR_SINF(endAngleRad)),
2944PNTR_API void pntr_draw_arc_thick(pntr_image* dst,
int centerX,
int centerY,
float radius,
float startAngle,
float endAngle,
int segments,
int thickness, pntr_color color) {
2945 if (radius <= 0.0f) {
2949 if (segments <= 0) {
2953 float startAngleRad = startAngle * PNTR_PI / 180.0f;
2954 float endAngleRad = endAngle * PNTR_PI / 180.0f;
2957 float stepAngle = (endAngleRad - startAngleRad) / (
float)(segments);
2960 int x1 = centerX + (int)((
float)radius *
PNTR_COSF(startAngleRad));
2961 int y1 = centerY + (int)((
float)radius *
PNTR_SINF(startAngleRad));
2963 for (
int i = 1; i < segments; i++) {
2964 angle = startAngleRad + (float)i * stepAngle;
2965 int x2 = centerX + (int)((
float)radius *
PNTR_COSF(angle));
2966 int y2 = centerY + (int)((
float)radius *
PNTR_SINF(angle));
2973PNTR_API void pntr_draw_arc_fill(pntr_image* dst,
int centerX,
int centerY,
float radius,
float startAngle,
float endAngle,
int segments, pntr_color color) {
2974 if (radius <= 0.0f) {
2978 if (segments <= 0) {
2981 float startAngleRad = startAngle * PNTR_PI / 180.0f;
2982 float endAngleRad = endAngle * PNTR_PI / 180.0f;
2985 float stepAngle = (endAngleRad - startAngleRad) / (
float)segments;
2986 pntr_vector* points = (pntr_vector*)PNTR_MALLOC(
sizeof(pntr_vector) * (size_t)segments + (
size_t)1);
2989 for (
int i = 0; i < segments; i++) {
2990 endAngleRad = startAngleRad + (float)i * stepAngle;
2991 points[i].x = centerX + (int)(radius *
PNTR_COSF(endAngleRad));
2992 points[i].y = centerY + (int)(radius *
PNTR_SINF(endAngleRad));
2995 points[segments].x = centerX;
2996 points[segments].y = centerY;
2998 pntr_draw_polygon_fill(dst, points, segments + 1, color);
3002PNTR_API void pntr_draw_rectangle_rounded(pntr_image* dst,
int x,
int y,
int width,
int height,
int topLeftRadius,
int topRightRadius,
int bottomLeftRadius,
int bottomRightRadius, pntr_color color) {
3003 if (topLeftRadius == 0 && topRightRadius == 0 && bottomLeftRadius == 0 && bottomRightRadius == 0) {
3009 pntr_draw_line_horizontal(dst, x + bottomLeftRadius, y + height, width - bottomLeftRadius - bottomRightRadius - 1, color);
3011 pntr_draw_line_vertical(dst, x + width - 1, y + topRightRadius, height - topRightRadius - bottomRightRadius, color);
3014 pntr_draw_arc(dst, x + topLeftRadius, y + topLeftRadius, (
float)topLeftRadius, 180.0f, 270.0f, topLeftRadius * 2, color);
3015 pntr_draw_arc(dst, x + width - topRightRadius - 1, y + topRightRadius, (
float)topRightRadius, 0.0f, -90.0f, topRightRadius * 2, color);
3016 pntr_draw_arc(dst, x + bottomLeftRadius, y + height - bottomLeftRadius, (
float)bottomLeftRadius, -180.0f, -270.0f, bottomLeftRadius * 2, color);
3017 pntr_draw_arc(dst, x + width - bottomRightRadius - 1, y + height - bottomRightRadius, (
float)bottomRightRadius, 0.0f, 90.0f, bottomRightRadius * 2, color);
3020PNTR_API void pntr_draw_rectangle_thick_rounded(pntr_image* dst,
int x,
int y,
int width,
int height,
int topLeftRadius,
int topRightRadius,
int bottomLeftRadius,
int bottomRightRadius,
int thickness, pntr_color color) {
3021 if (thickness < 1) {
3024 if (thickness == 1) {
3025 pntr_draw_rectangle_rounded(dst, x, y, width, height, topLeftRadius, topRightRadius, bottomLeftRadius, bottomRightRadius, color);
3028 for (
int offset = 0; offset < thickness; offset++ ) {
3029 pntr_draw_line_horizontal(dst, x + topLeftRadius - offset, y - offset, width - topLeftRadius - topRightRadius - offset, color);
3030 pntr_draw_line_horizontal(dst, x + bottomLeftRadius - offset, y + height - offset, width - bottomLeftRadius - bottomRightRadius - 1 - offset, color);
3031 pntr_draw_line_vertical(dst, x - offset, y + topLeftRadius - offset, height - topLeftRadius - bottomLeftRadius - offset, color);
3032 pntr_draw_line_vertical(dst, x + width - 1 - offset, y + topRightRadius - offset, height - topRightRadius - bottomRightRadius - offset, color);
3034 pntr_draw_arc_thick(dst, x + topLeftRadius, y + topLeftRadius, (
float)topLeftRadius, 180.0f, 270.0f, topLeftRadius * 2, thickness, color);
3035 pntr_draw_arc_thick(dst, x + width - topRightRadius - 1, y + topRightRadius, (
float)topRightRadius, 0.0f, -90.0f, topRightRadius * 2, thickness, color);
3036 pntr_draw_arc_thick(dst, x + bottomLeftRadius, y + height - bottomLeftRadius, (
float)bottomLeftRadius, -180.0f, -270.0f, bottomLeftRadius * 2, thickness, color);
3037 pntr_draw_arc_thick(dst, x + width - bottomRightRadius - 1, y + height - bottomRightRadius, (
float)bottomRightRadius, 0.0f, 90.0f, bottomRightRadius * 2, thickness, color);
3040PNTR_API void pntr_draw_rectangle_rounded_fill(pntr_image* dst,
int x,
int y,
int width,
int height,
int cornerRadius, pntr_color color) {
3041 if (cornerRadius == 0) {
3051 pntr_draw_circle_fill(dst, x + width - cornerRadius - 1, y + height - cornerRadius, cornerRadius, color);
3055 pntr_draw_rectangle_fill(dst, x + width - cornerRadius - 1, y + cornerRadius, cornerRadius, height - cornerRadius * 2, color);
3057 pntr_draw_rectangle_fill(dst, x + cornerRadius, y + height - cornerRadius, width - cornerRadius * 2, cornerRadius, color);
3060 pntr_draw_rectangle_fill(dst, x + cornerRadius, y + cornerRadius, width - cornerRadius * 2, height - cornerRadius * 2, color);
3073 if (image == NULL || x < 0 || y < 0 || x >= image->width || y >= image->height) {
3093 if (filePath == NULL) {
3094 return PNTR_IMAGE_TYPE_UNKNOWN;
3097 if (PNTR_STRSTR(filePath,
".png") != NULL || PNTR_STRSTR(filePath,
".PNG") != NULL) {
3098 return PNTR_IMAGE_TYPE_PNG;
3101 if (PNTR_STRSTR(filePath,
".bmp") != NULL || PNTR_STRSTR(filePath,
".BMP") != NULL) {
3102 return PNTR_IMAGE_TYPE_BMP;
3105 if (PNTR_STRSTR(filePath,
".jpg") != NULL || PNTR_STRSTR(filePath,
".jpeg") != NULL || PNTR_STRSTR(filePath,
".JPG") != NULL || PNTR_STRSTR(filePath,
".JPEG") != NULL) {
3106 return PNTR_IMAGE_TYPE_JPG;
3109 return PNTR_IMAGE_TYPE_UNKNOWN;
3113#ifndef PNTR_LOAD_IMAGE_FROM_MEMORY
3114 #ifdef PNTR_STB_IMAGE
3115 #include "extensions/pntr_stb_image.h"
3116 #elif defined(PNTR_CUTE_PNG)
3117 #include "extensions/pntr_cute_png.h"
3120 #ifdef PNTR_NO_LOAD_IMAGE
3121 #define PNTR_LOAD_IMAGE_FROM_MEMORY(type, fileData, dataSize) NULL
3124 #include "extensions/pntr_stb_image.h"
3129#ifndef PNTR_SAVE_IMAGE_TO_MEMORY
3130 #ifdef PNTR_STB_IMAGE
3131 #include "extensions/pntr_stb_image_write.h"
3132 #elif defined(PNTR_CUTE_PNG)
3133 #include "extensions/pntr_cute_png.h"
3136 #ifdef PNTR_NO_SAVE_IMAGE
3137 #define PNTR_SAVE_IMAGE_TO_MEMORY(image, type, dataSize) NULL
3140 #include "extensions/pntr_stb_image_write.h"
3160 if (fileData == NULL || dataSize == 0) {
3177 if (fileName == NULL) {
3181 unsigned int bytesRead;
3182 const unsigned char* fileData =
pntr_load_file(fileName, &bytesRead);
3183 if (fileData == NULL) {
3208 PNTR_CLITERAL(pntr_rectangle) { 0, 0, src->width, src->height },
3226 PNTR_CLITERAL(pntr_rectangle) { 0, 0, src->width, src->height },
3227 posX, posY, PNTR_WHITE);
3273 if (dst == NULL || src == NULL || posX >= dst->clip.x + dst->clip.width || posY >= dst->clip.y + dst->clip.height) {
3278 if (!_pntr_rectangle_intersect(srcRect.x, srcRect.y,
3279 srcRect.width <= 0 ? src->width : srcRect.width,
3280 srcRect.height <= 0 ? src->height : srcRect.height,
3282 src->width, src->height, &srcRect)) {
3287 if (posX < dst->clip.x) {
3288 srcRect.x -= posX - dst->clip.x;
3289 srcRect.width += posX - dst->clip.x;
3292 if (posY < dst->clip.y) {
3293 srcRect.y -= posY - dst->clip.y;
3294 srcRect.height += posY - dst->clip.y;
3299 pntr_rectangle dstRect = PNTR_CLITERAL(pntr_rectangle) { posX, posY, srcRect.width, srcRect.height };
3300 if (!_pntr_rectangle_intersect(dstRect.x, dstRect.y,
3303 dst->clip.x, dst->clip.y,
3304 dst->clip.width, dst->clip.height, &dstRect)) {
3309 int dst_skip = dst->pitch >> 2;
3310 int src_skip = src->pitch >> 2;
3313 pntr_color *dstPixel = dst->data + dst_skip * dstRect.y + dstRect.x;
3314 pntr_color *srcPixel = src->data + src_skip * srcRect.y + srcRect.x;
3316 if (tint.value == PNTR_WHITE_VALUE) {
3317 while (dstRect.height-- > 0) {
3318 for (
int x = 0; x < dstRect.width; ++x) {
3322 dstPixel += dst_skip;
3323 srcPixel += src_skip;
3327 while (dstRect.height-- > 0) {
3328 for (
int x = 0; x < dstRect.width; ++x) {
3332 dstPixel += dst_skip;
3333 srcPixel += src_skip;
3351 if (imageData == NULL || width <= 0 || height <= 0 || pixelFormat < 0) {
3356 switch (pixelFormat) {
3357 case PNTR_PIXELFORMAT_GRAYSCALE: {
3359 if (output == NULL) {
3363 unsigned char* source = (
unsigned char*)imageData;
3364 for (
int i = 0; i < width * height; i++) {
3371 case PNTR_PIXELFORMAT_ARGB8888:
3372 case PNTR_PIXELFORMAT_RGBA8888: {
3375 pntr_color* source = (pntr_color*)imageData;
3376 for (
int i = 0; i < width * height; i++) {
3402 if (image == NULL || scaleX <= 0.0f || scaleY <= 0.0f) {
3406 return pntr_image_resize(image, (
int)((
float)image->width * scaleX), (
int)((
float)image->height * scaleY), filter);
3422 if (image == NULL || newWidth <= 0 || newHeight <= 0 || filter < 0) {
3427 if (output == NULL) {
3432 case PNTR_FILTER_BILINEAR: {
3433 float xRatio = (float)image->width / (
float)newWidth;
3434 float yRatio = (float)image->height / (
float)newHeight;
3436 for (
int y = 0; y < newHeight; y++) {
3437 float srcY = (float)y * yRatio;
3438 int srcYPixel = (int)srcY;
3439 int srcYPixelPlusOne = y == newHeight - 1 ? (int)srcY : (int)srcY + 1;
3440 for (
int x = 0; x < newWidth; x++) {
3441 float srcX = (float)x * xRatio;
3442 int srcXPixel = (int)srcX;
3443 int srcXPixelPlusOne = x == newWidth - 1 ? (int)srcX : (int)srcX + 1;
3445 image->data[srcYPixel * (image->pitch >> 2) + srcXPixel],
3446 image->data[srcYPixelPlusOne * (image->pitch >> 2) + srcXPixel],
3447 image->data[srcYPixel * (image->pitch >> 2) + srcXPixelPlusOne],
3448 image->data[srcYPixelPlusOne * (image->pitch >> 2) + srcXPixelPlusOne],
3456 case PNTR_FILTER_NEARESTNEIGHBOR:
3458 int xRatio = (image->width << 16) / newWidth + 1;
3459 int yRatio = (image->height << 16) / newHeight + 1;
3461 for (
int y = 0; y < newHeight; y++) {
3462 int y2 = (y * yRatio) >> 16;
3463 for (
int x = 0; x < newWidth; x++) {
3486 if (image == NULL) {
3492 for (
int y = 0; y < image->height / 2; y++) {
3493 for (
int x = 0; x < image->width; x++) {
3496 PNTR_PIXEL(image, x, image->height - 1 - y) = swap;
3502 for (
int y = 0; y < image->height; y++) {
3503 for (
int x = 0; x < image->width / 2; x++) {
3506 PNTR_PIXEL(image, image->width - 1 - x, y) = swap;
3520 if (image == NULL) {
3524 for (
int y = image->clip.y; y < image->clip.y + image->clip.height; y++) {
3525 pntr_color* pixel = &
PNTR_PIXEL(image, 0, y);
3526 for (
int x = image->clip.x; x < image->clip.x + image->clip.width; x++) {
3527 if (pixel->value == color.value) {
3546 if (tint.value == PNTR_WHITE_VALUE) {
3551 (
unsigned char)(((
float)color.rgba.r / 255.0f * (
float)tint.rgba.r / 255.0f) * 255.0f),
3552 (
unsigned char)(((
float)color.rgba.g / 255.0f * (
float)tint.rgba.g / 255.0f) * 255.0f),
3553 (
unsigned char)(((
float)color.rgba.b / 255.0f * (
float)tint.rgba.b / 255.0f) * 255.0f),
3554 (
unsigned char)(((
float)color.rgba.a / 255.0f * (
float)tint.rgba.a / 255.0f) * 255.0f)
3567 if (factor < -1.0f) {
3570 else if (factor > 1.0f) {
3574 if (factor < 0.0f) {
3575 factor = 1.0f + factor;
3576 color.rgba.r = (
unsigned char)((
float)color.rgba.r * factor);
3577 color.rgba.g = (
unsigned char)((
float)color.rgba.g * factor);
3578 color.rgba.b = (
unsigned char)((
float)color.rgba.b * factor);
3581 color.rgba.r = (
unsigned char)(((
float)(255 - color.rgba.r) * factor) + color.rgba.r);
3582 color.rgba.g = (
unsigned char)(((
float)(255 - color.rgba.g) * factor) + color.rgba.g);
3583 color.rgba.b = (
unsigned char)(((
float)(255 - color.rgba.b) * factor) + color.rgba.b);
3600 if (factor < -1.0f) {
3603 else if (factor > 1.0f) {
3607 if (factor < 0.0f) {
3608 color.rgba.a = (
unsigned char)((
float)color.rgba.a * (1.0f + factor));
3611 color.rgba.a = (
unsigned char)(((
float)(255 - color.rgba.a) * factor) + color.rgba.a);
3626 if (image == NULL) {
3630 if (factor < -1.0f) {
3633 else if (factor > 1.0f) {
3637 for (
int y = image->clip.y; y < image->clip.y + image->clip.height; y++) {
3638 pntr_color* pixel = &
PNTR_PIXEL(image, image->clip.x, y);
3639 for (
int x = 0; x < image->clip.width; x++) {
3640 if (pixel->rgba.a > 0) {
3657 *((pntr_color*)dstPtr) = color;
3661 switch (dstPixelFormat) {
3662 case PNTR_PIXELFORMAT_RGBA8888:
3663 *((uint32_t*)(dstPtr)) = ((uint32_t)color.rgba.a << 24) | ((uint32_t)color.rgba.b << 16) | ((uint32_t)color.rgba.g << 8) | (uint32_t)color.rgba.r;
3665 case PNTR_PIXELFORMAT_ARGB8888:
3666 *((uint32_t*)(dstPtr)) = ((uint32_t)color.rgba.b << 24) | ((uint32_t)color.rgba.g << 16) | ((uint32_t)color.rgba.r << 8) | (uint32_t)color.rgba.a;
3668 case PNTR_PIXELFORMAT_GRAYSCALE: {
3669 float r = (float)color.rgba.r / 255.0f;
3670 float g = (float)color.rgba.g / 255.0f;
3671 float b = (float)color.rgba.b / 255.0f;
3672 ((
unsigned char *)dstPtr)[0] = (
unsigned char)((r * 0.299f + g * 0.587f + b * 0.114f) * 255.0f);
3687 switch (srcPixelFormat) {
3688 case PNTR_PIXELFORMAT_RGBA8888:
3690 ((
unsigned char *)srcPtr)[0],
3691 ((
unsigned char *)srcPtr)[1],
3692 ((
unsigned char *)srcPtr)[2],
3693 ((
unsigned char *)srcPtr)[3]
3695 case PNTR_PIXELFORMAT_ARGB8888:
3697 ((
unsigned char *)srcPtr)[1],
3698 ((
unsigned char *)srcPtr)[2],
3699 ((
unsigned char *)srcPtr)[3],
3700 ((
unsigned char *)srcPtr)[0]
3702 case PNTR_PIXELFORMAT_GRAYSCALE:
3704 return PNTR_NEW_COLOR(255, 255, 255, ((
unsigned char*)srcPtr)[0]);
3719 if (image == NULL) {
3723 for (
int y = image->clip.y; y < image->clip.y + image->clip.height; y++) {
3724 pntr_color* pixel = &
PNTR_PIXEL(image, image->clip.x, y);
3725 for (
int x = 0; x < image->clip.width; x++) {
3744 if (image == NULL) {
3761 if (fileData == NULL || dataSize == 0 || characters == NULL) {
3766 if (image == NULL) {
3784PNTR_API pntr_font* _pntr_new_font(
int numCharacters,
size_t characterByteSize, pntr_image* atlas) {
3785 if (numCharacters <= 0) {
3790 pntr_font* font = (pntr_font*)PNTR_MALLOC(
sizeof(pntr_font));
3796 font->srcRects = (pntr_rectangle*)PNTR_MALLOC(
sizeof(pntr_rectangle) * (size_t)numCharacters);
3797 if (font->srcRects == NULL) {
3803 font->glyphRects = (pntr_rectangle*)PNTR_MALLOC(
sizeof(pntr_rectangle) * (size_t)numCharacters);
3804 if (font->glyphRects == NULL) {
3805 PNTR_FREE(font->srcRects);
3811 font->characters = (
char*)PNTR_MALLOC(characterByteSize);
3812 if (font->characters == NULL) {
3813 PNTR_FREE(font->srcRects);
3814 PNTR_FREE(font->glyphRects);
3819 font->characters[0] =
'\0';
3820 font->charactersLen = numCharacters;
3821 font->atlas = atlas;
3835 if (image == NULL || characters == NULL) {
3840 size_t charactersSize = PNTR_STRSIZE(characters);
3842 pntr_rectangle currentRectangle = PNTR_CLITERAL(pntr_rectangle) {1, 0, 0, image->height};
3845 int numCharacters = 0;
3846 for (
int i = 0; i < image->width; i++) {
3853 pntr_font* font = _pntr_new_font(numCharacters, charactersSize, image);
3860 int currentCharacter = 0;
3861 for (
int i = 1; i < image->width; i++) {
3863 font->srcRects[currentCharacter] = currentRectangle;
3864 font->glyphRects[currentCharacter] = PNTR_CLITERAL(pntr_rectangle) {
3867 .width = currentRectangle.width,
3868 .height = currentRectangle.height,
3870 currentRectangle.width = 0;
3871 currentRectangle.x = i + 1;
3876 currentRectangle.width++;
3880 PNTR_MEMCPY(font->characters, characters, charactersSize);
3899 if (image == NULL) {
3903 pntr_font* output = pntr_load_font_tty_from_image(image, glyphWidth, glyphHeight, characters);
3904 if (output == NULL) {
3911PNTR_API pntr_font* pntr_load_font_tty_from_memory(
const unsigned char* fileData,
unsigned int dataSize,
int glyphWidth,
int glyphHeight,
const char* characters) {
3912 if (fileData == NULL || dataSize == 0 || characters == NULL || glyphWidth <= 0 || glyphHeight <= 0) {
3917 if (image == NULL) {
3921 pntr_font* output = pntr_load_font_tty_from_image(image, glyphWidth, glyphHeight, characters);
3922 if (output == NULL) {
3929PNTR_API pntr_font* pntr_load_font_tty_from_image(pntr_image* image,
int glyphWidth,
int glyphHeight,
const char* characters) {
3930 if (image == NULL || characters == NULL || glyphWidth <= 0 || glyphHeight <= 0) {
3935 int numCharacters = (int)PNTR_STRLEN(characters);
3936 size_t charactersSize = PNTR_STRSIZE(characters);
3939 pntr_font* font = _pntr_new_font(numCharacters, charactersSize, image);
3945 for (
int currentCharIndex = 0; currentCharIndex < numCharacters; currentCharIndex++) {
3947 font->srcRects[currentCharIndex] = PNTR_CLITERAL(pntr_rectangle) {
3948 .x = (currentCharIndex % (image->width / glyphWidth)) * glyphWidth,
3949 .y = (currentCharIndex / (image->width / glyphWidth)) * glyphHeight,
3950 .width = glyphWidth,
3951 .height = glyphHeight
3955 font->glyphRects[currentCharIndex] = PNTR_CLITERAL(pntr_rectangle) {
3958 .width = glyphWidth,
3959 .height = glyphHeight,
3963 PNTR_MEMCPY(font->characters, characters, charactersSize);
3998 if (atlas == NULL) {
4002 size_t charactersSize = PNTR_STRSIZE(font->characters);
4003 pntr_font* output = _pntr_new_font(font->charactersLen, charactersSize, atlas);
4004 if (output == NULL) {
4009 PNTR_MEMCPY(output->srcRects, font->srcRects,
sizeof(pntr_rectangle) * (
size_t)output->charactersLen);
4010 PNTR_MEMCPY(output->glyphRects, font->glyphRects,
sizeof(pntr_rectangle) * (
size_t)output->charactersLen);
4011 PNTR_MEMCPY(output->characters, font->characters, charactersSize);
4027 if (font == NULL || scaleX <= 0.0f || scaleY <= 0.0f) {
4033 if (output == NULL) {
4038 pntr_image* resizedAtlas =
pntr_image_scale(output->atlas, scaleX, scaleY, filter);
4040 output->atlas = resizedAtlas;
4043 for (
int i = 0; i < font->charactersLen; i++) {
4044 output->srcRects[i].x = (int)((
float)output->srcRects[i].x * scaleX);
4045 output->srcRects[i].y = (int)((
float)output->srcRects[i].y * scaleY);
4046 output->srcRects[i].width = (int)((
float)output->srcRects[i].width * scaleX);
4047 output->srcRects[i].height = (int)((
float)output->srcRects[i].height * scaleY);
4048 output->glyphRects[i].x = (int)((
float)output->glyphRects[i].x * scaleX);
4049 output->glyphRects[i].y = (int)((
float)output->glyphRects[i].y * scaleY);
4050 output->glyphRects[i].width = (int)((
float)output->glyphRects[i].width * scaleX);
4051 output->glyphRects[i].height = (int)((
float)output->glyphRects[i].height * scaleY);
4071 if (dst == NULL || font == NULL || text == NULL) {
4077 int tallestCharacter = 0;
4080 pntr_codepoint_t codepoint;
4082 for (
const char* v = PNTR_STRCODEPOINT(text, &codepoint); codepoint; v = PNTR_STRCODEPOINT(v, &codepoint)) {
4084 if (textLength > 0) {
4085 if (++count > textLength) {
4091 if (codepoint ==
'\n') {
4094 y += tallestCharacter;
4099 char* foundCharacter = PNTR_STRCHR(font->characters, codepoint);
4100 if (!foundCharacter) {
4105 #ifdef PNTR_ENABLE_UTF8
4106 int i = (int)utf8nlen(font->characters, (
size_t)(foundCharacter - font->characters));
4108 int i = (int)(foundCharacter - font->characters);
4112 if (codepoint !=
' ') {
4113 pntr_draw_image_tint_rec(dst, font->atlas, font->srcRects[i], x + font->glyphRects[i].x, y + font->glyphRects[i].y, tint);
4116 x += font->glyphRects[i].x + font->glyphRects[i].width;
4117 if (tallestCharacter < font->glyphRects[i].y + font->glyphRects[i].height) {
4118 tallestCharacter = font->glyphRects[i].y + font->glyphRects[i].height;
4153 if (dst == NULL || font == NULL || text == NULL) {
4157 pntr_codepoint_t codepoint;
4158 char* currentChar = (
char*)text;
4159 char* lineStart = currentChar;
4161 char* lastSpace = NULL;
4163 pntr_vector textSize = {0, 0};
4166 for (
char* nextChar = PNTR_STRCODEPOINT(text, &codepoint); codepoint; nextChar = PNTR_STRCODEPOINT(nextChar, &codepoint)) {
4167 if (codepoint ==
' ' || codepoint ==
'\n') {
4169 if (textSize.x > maxWidth) {
4170 if (lastSpace != NULL) {
4171 #ifdef PNTR_ENABLE_UTF8
4172 lineLength = (int)utf8nlen(lineStart, (
size_t)(lastSpace - lineStart));
4174 lineLength = (int)(lastSpace - lineStart);
4177 currentY += textSize.y;
4178 lineStart = lastSpace + 1;
4179 #ifdef PNTR_ENABLE_UTF8
4180 lineLength = (int)utf8nlen(lineStart, (
size_t)(currentChar - lineStart));
4182 lineLength = (int)(currentChar - lineStart);
4188 currentY += textSize.y;
4189 lineStart = nextChar;
4193 else if (codepoint ==
'\n') {
4194 #ifdef PNTR_ENABLE_UTF8
4195 lineLength = (int)utf8nlen(lineStart, (
size_t)(currentChar - lineStart));
4197 lineLength = (int)(currentChar - lineStart);
4200 currentY += textSize.y;
4201 lineStart = nextChar;
4206 lastSpace = currentChar;
4210 currentChar = nextChar;
4216 #ifdef PNTR_ENABLE_UTF8
4217 lineLength = (int)utf8nlen(lineStart, (
size_t)(lastSpace - lineStart));
4219 lineLength = (int)(lastSpace - lineStart);
4222 currentY += textSize.y;
4223 lineStart = lastSpace + 1;
4226 pntr_draw_text(dst, font, lineStart, posX, posY + currentY, tint);
4229#ifdef PNTR_ENABLE_VARGS
4247PNTR_API void pntr_draw_text_ex(pntr_image* dst, pntr_font* font,
int posX,
int posY, pntr_color tint,
int maxlen,
const char* text, ...) {
4248 #ifndef PNTR_DRAW_TEXT_EX_STRING_LENGTH
4252 #define PNTR_DRAW_TEXT_EX_STRING_LENGTH 512
4254 int length = (maxlen > 0) ? maxlen : PNTR_DRAW_TEXT_EX_STRING_LENGTH;
4255 char output[length];
4258 va_start(arg_ptr, text);
4259 vsnprintf(output, length, text, arg_ptr);
4288 if (font == NULL || text == NULL) {
4289 return PNTR_CLITERAL(pntr_vector){0, 0};
4292 pntr_vector output = PNTR_CLITERAL(pntr_vector) { .x = 0, .y = 0 };
4297 pntr_codepoint_t codepoint;
4298 for (
const char* v = PNTR_STRCODEPOINT(text, &codepoint); codepoint; v = PNTR_STRCODEPOINT(v, &codepoint)) {
4300 if (textLength > 0 && index++ >= textLength) {
4305 if (codepoint ==
'\n') {
4306 output.y += currentY;
4312 char* foundCharacter = PNTR_STRCHR(font->characters, codepoint);
4313 if (foundCharacter != NULL) {
4315 #ifdef PNTR_ENABLE_UTF8
4316 int i = (int)utf8nlen(font->characters, (
size_t)(foundCharacter - font->characters));
4318 int i = (int)(foundCharacter - font->characters);
4321 currentX += font->glyphRects[i].x + font->glyphRects[i].width;
4322 if (currentX > output.x) {
4323 output.x = currentX;
4327 if (currentY < font->glyphRects[i].y + font->glyphRects[i].height) {
4328 currentY = font->glyphRects[i].y + font->glyphRects[i].height;
4334 output.y += currentY;
4351 if (size.x <= 0 || size.y <= 0) {
4356 if (output == NULL) {
4383 #ifdef PNTR_DEFAULT_FONT
4384 return PNTR_DEFAULT_FONT();
4385 #elif defined(PNTR_ENABLE_DEFAULT_FONT)
4388 #include "external/font8x8_basic.h"
4391 #define PNTR_DEFAULT_FONT_NAME font8x8_basic
4392 #define PNTR_DEFAULT_FONT_GLYPH_WIDTH 8
4393 #define PNTR_DEFAULT_FONT_GLYPH_HEIGHT 8
4394 #define PNTR_DEFAULT_FONT_CHARACTERS_LEN 95
4398 PNTR_DEFAULT_FONT_GLYPH_WIDTH * PNTR_DEFAULT_FONT_CHARACTERS_LEN,
4399 PNTR_DEFAULT_FONT_GLYPH_HEIGHT,
4401 if (atlas == NULL) {
4406 for (
int i = 0; i < PNTR_DEFAULT_FONT_CHARACTERS_LEN; i++) {
4407 const unsigned char* bitmap = PNTR_DEFAULT_FONT_NAME[i];
4408 for (
int x = 0; x < 8; x++) {
4409 for (
int y = 0; y < 8; y++) {
4410 if (bitmap[y] & 1 << x) {
4411 pntr_draw_point(atlas, PNTR_DEFAULT_FONT_GLYPH_WIDTH * i + x, y, PNTR_WHITE);
4418 char characters[PNTR_DEFAULT_FONT_CHARACTERS_LEN + 1];
4419 for (
int i = 0; i < PNTR_DEFAULT_FONT_CHARACTERS_LEN; i++) {
4420 characters[i] = (char)(i + 32);
4422 characters[PNTR_DEFAULT_FONT_CHARACTERS_LEN] =
'\0';
4425 pntr_font* font = pntr_load_font_tty_from_image(atlas, PNTR_DEFAULT_FONT_GLYPH_WIDTH, PNTR_DEFAULT_FONT_GLYPH_HEIGHT, characters);
4452 if (fileName == NULL || fontSize <= 0) {
4456 #ifndef PNTR_ENABLE_TTF
4459 unsigned int bytesRead;
4461 if (fileData == NULL) {
4488 if (fileData == NULL || dataSize == 0 || fontSize <= 0) {
4492 #ifndef PNTR_ENABLE_TTF
4496 #define PNTR_FONT_TTF_GLYPH_START 32
4499 #ifndef PNTR_FONT_TTF_GLYPH_NUM
4500 #ifdef PNTR_ENABLE_UTF8
4503 #define PNTR_FONT_TTF_GLYPH_NUM 1295
4506 #define PNTR_FONT_TTF_GLYPH_NUM 95
4512 int rows = PNTR_FONT_TTF_GLYPH_NUM / columns;
4513 int width = fontSize * columns;
4514 int height = fontSize * rows;
4515 unsigned char* bitmap = (
unsigned char*)PNTR_MALLOC((
size_t)(width * height));
4516 if (bitmap == NULL) {
4521 stbtt_bakedchar characterData[PNTR_FONT_TTF_GLYPH_NUM];
4522 int result = stbtt_BakeFontBitmap(fileData, 0, (
float)fontSize, bitmap, width, height, PNTR_FONT_TTF_GLYPH_START, PNTR_FONT_TTF_GLYPH_NUM, characterData);
4533 if (atlas == NULL) {
4539 pntr_image_crop(atlas, 0, 0, crop.x + crop.width, crop.y + crop.height);
4542 size_t charactersSize =
sizeof(pntr_codepoint_t) * (
size_t)PNTR_FONT_TTF_GLYPH_NUM + 1;
4543 pntr_font* font = _pntr_new_font(PNTR_FONT_TTF_GLYPH_NUM, charactersSize, atlas);
4550 #ifdef PNTR_ENABLE_UTF8
4551 char* destination = font->characters;
4555 for (
int i = 0; i < PNTR_FONT_TTF_GLYPH_NUM; i++) {
4557 font->srcRects[i] = PNTR_CLITERAL(pntr_rectangle) {
4558 .x = characterData[i].x0,
4559 .y = characterData[i].y0,
4560 .width = characterData[i].x1 - characterData[i].x0,
4561 .height = characterData[i].y1 - characterData[i].y0
4565 font->glyphRects[i] = PNTR_CLITERAL(pntr_rectangle) {
4566 .x = (int)characterData[i].xoff,
4567 .y = (
int)(characterData[i].yoff + ((float)fontSize / 1.5f)),
4568 .width = (
int)characterData[i].xadvance,
4569 .height = (int)((
float)fontSize / 3.0f)
4573 #ifndef PNTR_ENABLE_UTF8
4574 font->characters[i] = (char)(PNTR_FONT_TTF_GLYPH_START + i);
4577 destination = utf8catcodepoint(destination, (pntr_codepoint_t)(PNTR_FONT_TTF_GLYPH_START + i), charactersSize - (
size_t)(destination - font->characters));
4582 #ifdef PNTR_ENABLE_UTF8
4583 destination[0] =
'\0';
4586 size_t newSize = PNTR_STRSIZE(font->characters);
4587 char* newCharacters = (
char*)PNTR_MALLOC(newSize);
4588 if (newCharacters != NULL) {
4589 PNTR_MEMCPY(newCharacters, font->characters, newSize);
4590 PNTR_FREE(font->characters);
4591 font->characters = newCharacters;
4594 font->characters[PNTR_FONT_TTF_GLYPH_NUM] =
'\0';
4612 (
unsigned char)(255 - color.rgba.r),
4613 (
unsigned char)(255 - color.rgba.g),
4614 (
unsigned char)(255 - color.rgba.b),
4627 if (image == NULL) {
4631 for (
int y = image->clip.y; y < image->clip.y + image->clip.height; y++) {
4632 pntr_color* pixel = &
PNTR_PIXEL(image, image->clip.x, y);
4633 for (
int x = 0; x < image->clip.width; x++) {
4649 if (image == NULL) {
4653 if (factor < -1.0f) {
4656 else if (factor > 1.0f) {
4660 for (
int y = image->clip.y; y < image->clip.y + image->clip.height; y++) {
4661 pntr_color* pixel = &
PNTR_PIXEL(image, image->clip.x, y);
4662 for (
int x = 0; x < image->clip.width; x++) {
4669#ifndef PNTR_LOAD_FILE
4670 #ifdef PNTR_NO_STDIO
4671 #define PNTR_LOAD_FILE(fileName, bytesRead) NULL
4693 if (fileName == NULL) {
4697 #ifdef PNTR_LOAD_FILE
4700 FILE* file = fopen(fileName,
"rb");
4702 if (bytesRead != NULL) {
4705 return (
unsigned char*)
pntr_set_error(PNTR_ERROR_FAILED_TO_OPEN);
4708 fseek(file, 0, SEEK_END);
4709 size_t size = (size_t)ftell(file);
4710 fseek(file, 0, SEEK_SET);
4714 if (bytesRead != NULL) {
4717 return (
unsigned char*)
pntr_set_error(PNTR_ERROR_FAILED_TO_OPEN);
4720 unsigned char* data = (
unsigned char*)PNTR_MALLOC(size *
sizeof(
unsigned char));
4723 if (bytesRead != NULL) {
4730 unsigned int bytes = (
unsigned int)fread(data,
sizeof(
unsigned char), size, file);
4732 if (bytesRead != NULL) {
4751 unsigned int bytesRead;
4759 char* output = (
char*)PNTR_MALLOC(bytesRead + 1);
4760 if (output == NULL) {
4765 PNTR_MEMCPY(output, data, bytesRead);
4766 output[bytesRead] =
'\0';
4768 return (
const char*)output;
4782#ifndef PNTR_SAVE_FILE
4783 #ifdef PNTR_NO_STDIO
4784 #define PNTR_SAVE_FILE(fileName, data, bytesToWrite) NULL
4804 if (fileName == NULL || data == NULL) {
4809 #ifdef PNTR_SAVE_FILE
4812 FILE *file = fopen(fileName,
"wb");
4818 size_t count = fwrite(data,
sizeof(
unsigned char), bytesToWrite, file);
4826 if (count != (
size_t)bytesToWrite) {
4832 return fclose(file) == 0;
4846 if (width <= 0 || height <= 0 || pixelFormat < 0) {
4850 int bitsPerPixel = 0;
4851 int bitsPerByte = 8;
4852 switch (pixelFormat) {
4853 case PNTR_PIXELFORMAT_RGBA8888:
4854 case PNTR_PIXELFORMAT_ARGB8888:
4855 bitsPerPixel = (int)
sizeof(pntr_color) * bitsPerByte;
4857 case PNTR_PIXELFORMAT_GRAYSCALE:
4858 bitsPerPixel = (int)
sizeof(
unsigned char) * bitsPerByte;
4861 bitsPerPixel = (int)
sizeof(pntr_color) * bitsPerByte;
4866 return bitsPerPixel * width * height / bitsPerByte;
4879 if (image == NULL) {
4884 if (imageSize <= 0) {
4888 void* data = PNTR_MALLOC((
size_t)imageSize);
4896 for (
int y = 0; y < image->height; y++) {
4897 for (
int x = 0; x < image->width; x++) {
4899 ((
unsigned char*)data) + (i++ * pixelSize),
4907 if (dataSize != NULL) {
4908 *dataSize = (
unsigned int)imageSize;
4931 if (image == NULL) {
4951 unsigned int dataSize;
4983 if (image == NULL) {
4984 return PNTR_CLITERAL(pntr_rectangle) {0, 0, 0, 0};
4987 unsigned char alphaThreshold = (
unsigned char)(threshold * 255.0f);
4993 for (
int y = 0; y < image->height; y++) {
4994 for (
int x = 0; x < image->width; x++) {
4995 if (image->data[y * (image->pitch >> 2) + x].rgba.a > alphaThreshold) {
5013 if ((xMin != 9999999) && (xMax != 9999999)) {
5014 return PNTR_CLITERAL(pntr_rectangle) {
5017 .width = xMax + 1 - xMin,
5018 .height = yMax + 1 - yMin
5022 return PNTR_CLITERAL(pntr_rectangle) {0, 0, 0, 0};
5037 if (image == NULL) {
5042 if (newImage == NULL) {
5047 if (!image->subimage) {
5048 PNTR_FREE(image->data);
5051 image->data = newImage->data;
5052 image->width = newImage->width;
5053 image->height = newImage->height;
5054 image->pitch = newImage->pitch;
5055 image->subimage =
false;
5058 PNTR_FREE(newImage);
5073 if (image == NULL) {
5079 if (crop.width > 0 && crop.height > 0) {
5093 if (contrast < -1.0f) {
5096 else if (contrast > 1.0f) {
5100 contrast = (1.0f + contrast) * contrast;
5102 float pR = (float)color.rgba.r / 255.0f - 0.5f;
5109 else if (pR > 255) {
5113 float pG = (float)color.rgba.g / 255.0f - 0.5f;
5120 else if (pG > 255) {
5124 float pB = (float)color.rgba.b / 255.0f - 0.5f;
5131 else if (pB > 255) {
5135 return PNTR_NEW_COLOR((
unsigned char)pR, (
unsigned char)pG, (
unsigned char)pB, color.rgba.a);
5147 if (image == NULL) {
5151 if (contrast < -1.0f) {
5154 else if (contrast > 1.0f) {
5158 for (
int y = image->clip.y; y < image->clip.y + image->clip.height; y++) {
5159 pntr_color* pixel = &
PNTR_PIXEL(image, image->clip.x, y);
5160 for (
int x = 0; x < image->clip.width; x++) {
5178 if (image == NULL || alphaMask == NULL) {
5182 pntr_rectangle srcRect = PNTR_CLITERAL(pntr_rectangle) { 0, 0, alphaMask->width, alphaMask->height };
5183 pntr_rectangle dstRect = PNTR_CLITERAL(pntr_rectangle) { posX, posY, alphaMask->width, alphaMask->height };
5186 if (dstRect.x < 0) {
5187 srcRect.x -= dstRect.x;
5188 srcRect.width += dstRect.x;
5190 if (dstRect.y < 0) {
5191 srcRect.y -= dstRect.y;
5192 srcRect.height += dstRect.y;
5195 if (!_pntr_rectangle_intersect(dstRect.x, dstRect.y,
5196 PNTR_MIN(dstRect.width, srcRect.width),
5197 PNTR_MIN(dstRect.height, srcRect.height),
5198 image->clip.x, image->clip.y,
5199 image->clip.width, image->clip.height, &dstRect)) {
5203 for (
int y = 0; y < dstRect.height; y++) {
5204 pntr_color* pixel = &
PNTR_PIXEL(image, dstRect.x, dstRect.y + y);
5205 for (
int x = 0; x < dstRect.width; x++) {
5206 if (pixel->rgba.a > 0) {
5207 pixel->rgba.a =
PNTR_PIXEL(alphaMask, x, y).rgba.a;
5227 if (image == NULL) {
5233 if (newImage == NULL) {
5240 if (!image->subimage) {
5241 PNTR_FREE(image->data);
5244 image->data = newImage->data;
5245 image->width = newImage->width;
5246 image->height = newImage->height;
5247 image->pitch = newImage->pitch;
5251 image->subimage =
false;
5253 PNTR_FREE(newImage);
5257PNTR_API void pntr_draw_image_flipped(pntr_image* dst, pntr_image* src,
int posX,
int posY,
bool flipHorizontal,
bool flipVertical,
bool flipDiagonal) {
5258 if (dst == NULL || src == NULL) {
5262 pntr_draw_image_flipped_rec(dst, src,
5263 PNTR_CLITERAL(pntr_rectangle) { .x = 0, .y = 0, .width = src->width, .height = src->height },
5271PNTR_API void pntr_draw_image_flipped_rec(pntr_image* dst, pntr_image* src, pntr_rectangle srcRec,
int posX,
int posY,
bool flipHorizontal,
bool flipVertical,
bool flipDiagonal) {
5273 if (!flipHorizontal && !flipVertical && !flipDiagonal) {
5278 if (dst == NULL || src == NULL) {
5282 if (!_pntr_rectangle_intersect(srcRec.x, srcRec.y, srcRec.width, srcRec.height, 0, 0, src->width, src->height, &srcRec)) {
5287 for (
int y = 0; y < srcRec.height; y++) {
5288 for (
int x = 0; x < srcRec.width; x++) {
5291 dstX = flipHorizontal ? srcRec.height - y - 1 : y;
5292 dstY = flipVertical ? srcRec.width - x - 1 : x;
5295 dstY = flipVertical ? srcRec.height - y - 1 : y;
5296 dstX = flipHorizontal ? srcRec.width - x - 1 : x;
5319PNTR_API void pntr_draw_image_scaled(pntr_image* dst, pntr_image* src,
int posX,
int posY,
float scaleX,
float scaleY,
float offsetX,
float offsetY, pntr_filter filter) {
5320 if (dst == NULL || src == NULL) {
5324 pntr_draw_image_scaled_rec(dst, src,
5325 PNTR_CLITERAL(pntr_rectangle) { .x = 0, .y = 0, .width = src->width, .height = src->height },
5332PNTR_API void pntr_draw_image_scaled_rec(pntr_image* dst, pntr_image* src, pntr_rectangle srcRect,
int posX,
int posY,
float scaleX,
float scaleY,
float offsetX,
float offsetY, pntr_filter filter) {
5333 if (dst == NULL || src == NULL || scaleX <= 0.0f || scaleY <= 0.0f) {
5337 if (!_pntr_rectangle_intersect(srcRect.x, srcRect.y, srcRect.width, srcRect.height, 0, 0, src->width, src->height, &srcRect)) {
5341 int newWidth = (int)((
float)srcRect.width * scaleX);
5342 int newHeight = (int)((
float)srcRect.height * scaleY);
5343 int offsetXRatio = (int)(offsetX / (
float)srcRect.width * (float)newWidth);
5344 int offsetYRatio = (int)(offsetY / (
float)srcRect.height * (float)newHeight);
5347 case PNTR_FILTER_BILINEAR: {
5348 float xRatio = (float)srcRect.width / (
float)newWidth;
5349 float yRatio = (float)srcRect.height / (
float)newHeight;
5351 for (
int y = 0; y < newHeight; y++) {
5352 int yPosition = posY + y - offsetYRatio;
5353 if (yPosition < dst->clip.y || yPosition >= dst->clip.y + dst->clip.height) {
5356 float srcY = (float)y * yRatio;
5357 int srcYPixel = srcRect.y + (int)srcY;
5358 int srcYPixelPlusOne = y == newHeight - 1 ? (int)srcYPixel : (int)srcYPixel + 1;
5359 for (
int x = 0; x < newWidth; x++) {
5360 int xPosition = posX + x - offsetXRatio;
5361 if (xPosition < dst->clip.x || xPosition >= dst->clip.x + dst->clip.width) {
5364 float srcX = (float)x * xRatio;
5365 int srcXPixel = srcRect.y + (int)srcX;
5366 int srcXPixelPlusOne = x == newWidth - 1 ? (int)srcXPixel : (int)srcXPixel + 1;
5368 src->data[srcYPixel * (src->pitch >> 2) + srcXPixel],
5369 src->data[srcYPixelPlusOne * (src->pitch >> 2) + srcXPixel],
5370 src->data[srcYPixel * (src->pitch >> 2) + srcXPixelPlusOne],
5371 src->data[srcYPixelPlusOne * (src->pitch >> 2) + srcXPixelPlusOne],
5379 case PNTR_FILTER_NEARESTNEIGHBOR:
5381 int xRatio = (srcRect.width << 16) / newWidth + 1;
5382 int yRatio = (srcRect.height << 16) / newHeight + 1;
5384 for (
int y = 0; y < newHeight; y++) {
5385 int yPosition = posY + y - offsetYRatio;
5386 if (yPosition < dst->clip.y || yPosition >= dst->clip.y + dst->clip.height) {
5389 int y2 = (y * yRatio) >> 16;
5390 for (
int x = 0; x < newWidth; x++) {
5391 int xPosition = posX + x - offsetXRatio;
5392 if (xPosition < dst->clip.x || xPosition >= dst->clip.x + dst->clip.width) {
5395 int x2 = (x * xRatio) >> 16;
5399 PNTR_PIXEL(src, srcRect.x + x2, srcRect.y + y2)
5417float _pntr_normalize_degrees(
float degrees) {
5419 return 360.0f -
PNTR_FMODF(-degrees, 360.0f);
5437 if (image == NULL) {
5441 degrees = _pntr_normalize_degrees(degrees);
5443 if (degrees == 0.0f) {
5447 if (degrees == 90.0f || degrees == 180.0f || degrees == 270.0f) {
5449 if (degrees == 180.0f) {
5455 if (output == NULL) {
5464 float radians = degrees * PNTR_DEG2RAD;
5472 if (rotatedImage == NULL) {
5478 return rotatedImage;
5500 (uint8_t)(color00.rgba.r * (1 - coordinateX) * (1 - coordinateY) + color01.rgba.r * (1 - coordinateX) * coordinateY + color10.rgba.r * coordinateX * (1 - coordinateY) + color11.rgba.r * coordinateX * coordinateY),
5501 (uint8_t)(color00.rgba.g * (1 - coordinateX) * (1 - coordinateY) + color01.rgba.g * (1 - coordinateX) * coordinateY + color10.rgba.g * coordinateX * (1 - coordinateY) + color11.rgba.g * coordinateX * coordinateY),
5502 (uint8_t)(color00.rgba.b * (1 - coordinateX) * (1 - coordinateY) + color01.rgba.b * (1 - coordinateX) * coordinateY + color10.rgba.b * coordinateX * (1 - coordinateY) + color11.rgba.b * coordinateX * coordinateY),
5503 (uint8_t)(color00.rgba.a * (1 - coordinateX) * (1 - coordinateY) + color01.rgba.a * (1 - coordinateX) * coordinateY + color10.rgba.a * coordinateX * (1 - coordinateY) + color11.rgba.a * coordinateX * coordinateY)
5523 if (dst == NULL || src == NULL) {
5528 PNTR_CLITERAL(pntr_rectangle) { .x = 0, .y = 0, .width = src->width, .height = src->height },
5551 if (dst == NULL || src == NULL) {
5555 degrees = _pntr_normalize_degrees(degrees);
5558 if (degrees == 0.0f) {
5564 if (srcRect.x < 0) {
5567 if (srcRect.y < 0) {
5570 if (srcRect.width <= 0 || srcRect.width > src->width) {
5571 srcRect.width = src->width - srcRect.x;
5573 if (srcRect.height <= 0 || srcRect.height > src->height) {
5574 srcRect.height = src->height - srcRect.y;
5578 if (degrees == 90.0f || degrees == 180.0f || degrees == 270.0f) {
5580 pntr_rectangle dstRect = PNTR_CLITERAL(pntr_rectangle) { .x = posX, .y = posY, .width = srcRect.width, .height = srcRect.height };
5581 if (degrees == 90.0f || degrees == 270.0f) {
5582 dstRect.width = srcRect.height;
5583 dstRect.height = srcRect.width;
5584 dstRect.x -= (int)offsetY;
5585 dstRect.y -= (int)offsetX;
5588 dstRect.x -= (int)offsetX;
5589 dstRect.y -= (int)offsetY;
5593 if (dstRect.x + dstRect.width < dst->clip.x || dstRect.y + dstRect.height < dst->clip.y || dstRect.x >= dst->clip.x + dst->clip.width || dstRect.y >= dst->clip.y + dst->clip.height) {
5598 for (
int y = 0; y < srcRect.height; y++) {
5599 for (
int x = 0; x < srcRect.width; x++) {
5600 if (degrees == 90.0f) {
5603 dstRect.y + srcRect.width - x,
5604 PNTR_PIXEL(src, srcRect.x + x, srcRect.y + y)
5606 }
else if (degrees == 180.0f) {
5608 dstRect.x + srcRect.width - x,
5609 dstRect.y + srcRect.height - y,
5610 PNTR_PIXEL(src, srcRect.x + x, srcRect.y + y)
5615 dstRect.x + srcRect.height - y,
5617 PNTR_PIXEL(src, srcRect.x + x, srcRect.y + y)
5626 float radians = degrees * PNTR_DEG2RAD;
5633 int offsetXRatio = (int)(offsetX / (
float)srcRect.width * (float)newWidth);
5634 int offsetYRatio = (int)(offsetY / (
float)srcRect.height * (float)newHeight);
5637 if (posX - offsetXRatio + newWidth < dst->clip.x || posX - offsetXRatio >= dst->clip.x + dst->clip.width || posY - offsetYRatio + newHeight < dst->clip.y || posY - offsetYRatio >= dst->clip.y + dst->clip.height) {
5641 float centerX = (float)srcRect.width / 2.0f;
5642 float centerY = (float)srcRect.height / 2.0f;
5643 int srcXint, srcYint;
5646 for (
int y = 0; y < newHeight; y++) {
5648 int destY = posY + y - offsetYRatio;
5649 if (destY < dst->clip.y || destY >= dst->clip.y + dst->clip.height) {
5653 for (
int x = 0; x < newWidth; x++) {
5655 int destX = posX + x - offsetXRatio;
5656 if (destX < dst->clip.x || destX >= dst->clip.x + dst->clip.width ) {
5660 srcX = (float)(x - newWidth / 2) * cosTheta - (float)(y - newHeight / 2) * sinTheta + centerX;
5661 srcY = (float)(x - newWidth / 2) * sinTheta + (float)(y - newHeight / 2) * cosTheta + centerY;
5664 if (srcX < 0 || srcX >= srcRect.width || srcY < 0 || srcY >= srcRect.height) {
5668 srcXint = (int)srcX + srcRect.x;
5669 srcYint = (int)srcY + srcRect.y;
5671 if (filter == PNTR_FILTER_NEARESTNEIGHBOR) {
5680 if (srcX >= srcRect.width - 1 || srcY >= srcRect.height - 1) {
5715 if (image == NULL) {
5719 pntr_draw_rectangle_gradient(image, 0, 0, width, height, topLeft, topRight, bottomLeft, bottomRight);
5732 if (image == NULL) {
5733 return PNTR_CLITERAL(pntr_rectangle) {
5757 if (image == NULL) {
5761 pntr_rectangle clip;
5762 if (_pntr_rectangle_intersect(x, y, width, height, 0, 0, image->width, image->height, &clip)) {
5788 if (image == NULL) {
5794 image->clip.width = image->width;
5795 image->clip.height = image->height;
5808 return PNTR_MALLOC(size);
5819 if (pointer == NULL) {
5838 return PNTR_MEMCPY(destination, source, size);
#define PNTR_MAX(a, b)
Definition pntr.h:1204
#define PNTR_SINF(value)
Definition pntr.h:1056
#define PNTR_FLOORF(x)
Definition pntr.h:1143
#define PNTR_FABSF(x)
Definition pntr.h:1130
#define PNTR_COSF(value)
Definition pntr.h:1088
#define PNTR_MIN(a, b)
Definition pntr.h:1216
#define PNTR_FMODF(dividend, divisor)
Definition pntr.h:1156
#define PNTR_CEILF(x)
Definition pntr.h:1117
#define PNTR_SAVE_IMAGE_TO_MEMORY
Definition pntr.h:153
#define PNTR_SAVE_FILE
Definition pntr.h:185
#define PNTR_LOAD_FILE
Definition pntr.h:177
#define PNTR_LOAD_IMAGE_FROM_MEMORY
Definition pntr.h:164
PNTR_API void pntr_draw_ellipse_thick(pntr_image *dst, int centerX, int centerY, int radiusX, int radiusY, int thickness, pntr_color color)
Definition pntr.h:2645
PNTR_API pntr_color pntr_color_invert(pntr_color color)
Definition pntr.h:4610
PNTR_API pntr_image * pntr_gen_image_color(int width, int height, pntr_color color)
Definition pntr.h:1500
PNTR_API pntr_font * pntr_load_font_ttf_from_memory(const unsigned char *fileData, unsigned int dataSize, int fontSize)
Definition pntr.h:4487
PNTR_API pntr_image * pntr_image_from_pixelformat(const void *imageData, int width, int height, pntr_pixelformat pixelFormat)
Definition pntr.h:3350
PNTR_API void pntr_draw_triangle_vec(pntr_image *dst, pntr_vector point1, pntr_vector point2, pntr_vector point3, pntr_color color)
Definition pntr.h:2697
PNTR_API void pntr_image_set_clip(pntr_image *image, int x, int y, int width, int height)
Definition pntr.h:5756
PNTR_API void pntr_image_set_clip_rec(pntr_image *image, pntr_rectangle clip)
Definition pntr.h:5776
PNTR_API pntr_color pntr_get_color(unsigned int hexValue)
Definition pntr.h:1778
PNTR_API void pntr_draw_circle(pntr_image *dst, int centerX, int centerY, int radius, pntr_color color)
Definition pntr.h:2391
PNTR_API void pntr_draw_image_rotated_rec(pntr_image *dst, pntr_image *src, pntr_rectangle srcRect, int posX, int posY, float degrees, float offsetX, float offsetY, pntr_filter filter)
Definition pntr.h:5550
PNTR_API void pntr_image_color_invert(pntr_image *image)
Definition pntr.h:4626
PNTR_API void pntr_draw_triangle_fill_vec(pntr_image *dst, pntr_vector point1, pntr_vector point2, pntr_vector point3, pntr_color color)
Definition pntr.h:2896
PNTR_API void pntr_unload_image(pntr_image *image)
Definition pntr.h:1697
PNTR_API void pntr_draw_line_horizontal(pntr_image *dst, int posX, int posY, int width, pntr_color color)
Definition pntr.h:2149
PNTR_API void pntr_blend_color(pntr_color *dst, pntr_color src)
Definition pntr.h:1543
PNTR_API void pntr_draw_line_thick(pntr_image *dst, int startPosX, int startPosY, int endPosX, int endPosY, int thickness, pntr_color color)
Definition pntr.h:1959
PNTR_API pntr_image * pntr_image_from_image(pntr_image *image, int x, int y, int width, int height)
Definition pntr.h:1625
PNTR_API void pntr_image_alpha_crop(pntr_image *image, float threshold)
Definition pntr.h:5072
PNTR_API void pntr_draw_image_scaled(pntr_image *dst, pntr_image *src, int posX, int posY, float scaleX, float scaleY, float offsetX, float offsetY, pntr_filter filter)
Definition pntr.h:5319
PNTR_API pntr_rectangle pntr_image_get_clip(pntr_image *image)
Definition pntr.h:5731
PNTR_API pntr_font * pntr_load_font_bmf_from_memory(const unsigned char *fileData, unsigned int dataSize, const char *characters)
Definition pntr.h:3760
PNTR_API void pntr_image_color_contrast(pntr_image *image, float contrast)
Definition pntr.h:5146
PNTR_API pntr_image * pntr_load_image(const char *fileName)
Definition pntr.h:3176
PNTR_API pntr_rectangle pntr_image_alpha_border(pntr_image *image, float threshold)
Definition pntr.h:4982
PNTR_API void pntr_draw_point(pntr_image *dst, int x, int y, pntr_color color)
Definition pntr.h:1829
PNTR_API void pntr_draw_triangle_fill(pntr_image *dst, int x1, int y1, int x2, int y2, int x3, int y3, pntr_color color)
Definition pntr.h:2767
PNTR_API pntr_image * pntr_new_image(int width, int height)
Definition pntr.h:1467
PNTR_API pntr_color pntr_color_alpha_blend(pntr_color dst, pntr_color src)
Definition pntr.h:3240
PNTR_API unsigned char * pntr_save_image_to_memory(pntr_image *image, pntr_image_type type, unsigned int *dataSize)
Definition pntr.h:4930
PNTR_API int pntr_measure_text(pntr_font *font, const char *text)
Definition pntr.h:4274
PNTR_API void pntr_draw_image_rec(pntr_image *dst, pntr_image *src, pntr_rectangle srcRect, int posX, int posY)
Definition pntr.h:3256
PNTR_API unsigned char * pntr_load_file(const char *fileName, unsigned int *bytesRead)
Definition pntr.h:4692
PNTR_API pntr_image * pntr_gen_image_gradient(int width, int height, pntr_color topLeft, pntr_color topRight, pntr_color bottomLeft, pntr_color bottomRight)
Definition pntr.h:5713
PNTR_API int pntr_get_pixel_data_size(int width, int height, pntr_pixelformat pixelFormat)
Definition pntr.h:4845
PNTR_API pntr_color pntr_color_bilinear_interpolate(pntr_color color00, pntr_color color01, pntr_color color10, pntr_color color11, float coordinateX, float coordinateY)
Definition pntr.h:5498
PNTR_API bool pntr_image_crop(pntr_image *image, int x, int y, int width, int height)
Definition pntr.h:5036
PNTR_API void pntr_put_horizontal_line_unsafe(pntr_image *dst, int posX, int posY, int width, pntr_color color)
Definition pntr.h:1713
PNTR_API void pntr_image_color_fade(pntr_image *image, float factor)
Definition pntr.h:3625
PNTR_API void pntr_draw_point_unsafe(pntr_image *dst, int x, int y, pntr_color color)
Definition pntr.h:1822
PNTR_API void pntr_image_color_tint(pntr_image *image, pntr_color tint)
Definition pntr.h:3718
PNTR_API pntr_color pntr_image_get_color(pntr_image *image, int x, int y)
Definition pntr.h:3072
PNTR_API pntr_image * pntr_load_image_from_memory(pntr_image_type type, const unsigned char *fileData, unsigned int dataSize)
Definition pntr.h:3159
PNTR_API const char * pntr_load_file_text(const char *fileName)
Definition pntr.h:4750
PNTR_API void pntr_draw_image(pntr_image *dst, pntr_image *src, int posX, int posY)
Definition pntr.h:3221
PNTR_API void pntr_draw_line(pntr_image *dst, int startPosX, int startPosY, int endPosX, int endPosY, pntr_color color)
Definition pntr.h:1863
PNTR_API bool pntr_save_image(pntr_image *image, const char *fileName)
Definition pntr.h:4949
PNTR_API bool pntr_save_file(const char *fileName, const void *data, unsigned int bytesToWrite)
Definition pntr.h:4803
PNTR_API void pntr_draw_triangle(pntr_image *dst, int x1, int y1, int x2, int y2, int x3, int y3, pntr_color color)
Definition pntr.h:2729
PNTR_API void pntr_unload_memory(void *pointer)
Definition pntr.h:5818
PNTR_API void pntr_draw_rectangle_rec(pntr_image *dst, pntr_rectangle rec, pntr_color color)
Definition pntr.h:2250
PNTR_API void pntr_draw_ellipse_fill(pntr_image *dst, int centerX, int centerY, int radiusX, int radiusY, pntr_color color)
Definition pntr.h:2597
PNTR_API void pntr_draw_rectangle_fill(pntr_image *dst, int posX, int posY, int width, int height, pntr_color color)
Definition pntr.h:2300
PNTR_API pntr_font * pntr_load_font_ttf(const char *fileName, int fontSize)
Definition pntr.h:4451
PNTR_API void pntr_draw_rectangle_fill_rec(pntr_image *dst, pntr_rectangle rect, pntr_color color)
Definition pntr.h:2313
PNTR_API void pntr_draw_text_len(pntr_image *dst, pntr_font *font, const char *text, int textLength, int posX, int posY, pntr_color tint)
Definition pntr.h:4070
PNTR_API pntr_color pntr_color_fade(pntr_color color, float factor)
Definition pntr.h:3599
PNTR_API void pntr_draw_text_wrapped(pntr_image *dst, pntr_font *font, const char *text, int posX, int posY, int maxWidth, pntr_color tint)
Definition pntr.h:4152
PNTR_API void * pntr_set_error(pntr_error error)
Definition pntr.h:1445
PNTR_API void pntr_draw_circle_thick(pntr_image *dst, int centerX, int centerY, int radius, int thickness, pntr_color color)
Definition pntr.h:2493
PNTR_API pntr_color pntr_new_color(unsigned char red, unsigned char green, unsigned char blue, unsigned char alpha)
Definition pntr.h:1767
PNTR_API pntr_image * pntr_image_resize(pntr_image *image, int newWidth, int newHeight, pntr_filter filter)
Definition pntr.h:3421
PNTR_API void pntr_set_pixel_color(void *dstPtr, pntr_pixelformat dstPixelFormat, pntr_color color)
Definition pntr.h:3655
PNTR_API void pntr_unload_file(unsigned char *fileData)
Definition pntr.h:4970
PNTR_API void pntr_draw_triangle_thick(pntr_image *dst, int x1, int y1, int x2, int y2, int x3, int y3, int thickness, pntr_color color)
Definition pntr.h:2748
PNTR_API pntr_image * pntr_gen_image_text(pntr_font *font, const char *text, pntr_color tint, pntr_color backgroundColor)
Definition pntr.h:4349
#define PNTR_PIXEL(image, x, y)
Definition pntr.h:1372
PNTR_API void pntr_draw_text(pntr_image *dst, pntr_font *font, const char *text, int posX, int posY, pntr_color tint)
Definition pntr.h:4135
PNTR_API pntr_font * pntr_load_font_tty(const char *fileName, int glyphWidth, int glyphHeight, const char *characters)
Definition pntr.h:3897
PNTR_API pntr_color pntr_color_brightness(pntr_color color, float factor)
Definition pntr.h:3566
PNTR_API void * pntr_memory_copy(void *destination, void *source, size_t size)
Definition pntr.h:5837
PNTR_API void pntr_image_color_brightness(pntr_image *image, float factor)
Definition pntr.h:4648
PNTR_API pntr_font * pntr_load_font_bmf(const char *fileName, const char *characters)
Definition pntr.h:3742
PNTR_API void pntr_unload_file_text(const char *text)
Definition pntr.h:4778
PNTR_API pntr_font * pntr_font_copy(pntr_font *font)
Definition pntr.h:3992
#define PNTR_API
Definition pntr.h:275
PNTR_API pntr_image_type pntr_get_file_image_type(const char *filePath)
Definition pntr.h:3092
PNTR_API pntr_color pntr_color_tint(pntr_color color, pntr_color tint)
Definition pntr.h:3545
PNTR_API void pntr_image_alpha_mask(pntr_image *image, pntr_image *alphaMask, int posX, int posY)
Definition pntr.h:5177
PNTR_API pntr_font * pntr_load_font_bmf_from_image(pntr_image *image, const char *characters)
Definition pntr.h:3834
PNTR_API void * pntr_image_to_pixelformat(pntr_image *image, unsigned int *dataSize, pntr_pixelformat pixelFormat)
Definition pntr.h:4878
PNTR_API pntr_font * pntr_load_font_default(void)
Definition pntr.h:4382
#define PNTR_PIXELFORMAT
Definition pntr.h:298
PNTR_API void pntr_image_color_replace(pntr_image *image, pntr_color color, pntr_color replace)
Definition pntr.h:3519
PNTR_API void pntr_image_reset_clip(pntr_image *image)
Definition pntr.h:5787
PNTR_API pntr_color pntr_get_pixel_color(void *srcPtr, pntr_pixelformat srcPixelFormat)
Definition pntr.h:3686
PNTR_API pntr_image * pntr_image_scale(pntr_image *image, float scaleX, float scaleY, pntr_filter filter)
Definition pntr.h:3401
PNTR_API void pntr_draw_image_tint_rec(pntr_image *dst, pntr_image *src, pntr_rectangle srcRect, int posX, int posY, pntr_color tint)
Definition pntr.h:3272
PNTR_API void pntr_draw_circle_fill(pntr_image *dst, int centerX, int centerY, int radius, pntr_color color)
Definition pntr.h:2448
PNTR_API void pntr_draw_ellipse(pntr_image *dst, int centerX, int centerY, int radiusX, int radiusY, pntr_color color)
Definition pntr.h:2547
#define PNTR_NEW_COLOR(red, green, blue, alpha)
Definition pntr.h:1388
PNTR_API void pntr_draw_rectangle(pntr_image *dst, int posX, int posY, int width, int height, pntr_color color)
Definition pntr.h:2267
PNTR_API pntr_color pntr_color_contrast(pntr_color color, float contrast)
Definition pntr.h:5092
PNTR_API pntr_image * pntr_image_subimage(pntr_image *image, int x, int y, int width, int height)
Definition pntr.h:1665
PNTR_API pntr_font * pntr_font_scale(pntr_font *font, float scaleX, float scaleY, pntr_filter filter)
Definition pntr.h:4026
PNTR_API void pntr_clear_background(pntr_image *image, pntr_color color)
Definition pntr.h:1728
PNTR_API void * pntr_load_memory(size_t size)
Definition pntr.h:5807
PNTR_API void pntr_image_flip(pntr_image *image, bool horizontal, bool vertical)
Definition pntr.h:3485
PNTR_API void pntr_draw_triangle_thick_vec(pntr_image *dst, pntr_vector point1, pntr_vector point2, pntr_vector point3, int thickness, pntr_color color)
Definition pntr.h:2711
PNTR_API pntr_image * pntr_image_copy(pntr_image *image)
Definition pntr.h:1514
PNTR_API pntr_image * pntr_image_rotate(pntr_image *image, float degrees, pntr_filter filter)
Definition pntr.h:5436
PNTR_API void pntr_draw_image_tint(pntr_image *dst, pntr_image *src, int posX, int posY, pntr_color tint)
Definition pntr.h:3203
PNTR_API bool pntr_image_resize_canvas(pntr_image *image, int newWidth, int newHeight, int offsetX, int offsetY, pntr_color fill)
Definition pntr.h:5226
PNTR_API void pntr_draw_line_vertical(pntr_image *dst, int posX, int posY, int height, pntr_color color)
Definition pntr.h:2201
PNTR_API pntr_vector pntr_measure_text_ex(pntr_font *font, const char *text, int textLength)
Definition pntr.h:4287
PNTR_API void pntr_draw_image_rotated(pntr_image *dst, pntr_image *src, int posX, int posY, float degrees, float offsetX, float offsetY, pntr_filter filter)
Definition pntr.h:5522
PNTR_API void pntr_unload_font(pntr_font *font)
Definition pntr.h:3973