From 115630b520668304af1ccd3eb0b13c06e17ecccc Mon Sep 17 00:00:00 2001 From: dec05eba Date: Sun, 24 Oct 2021 04:52:30 +0200 Subject: Add function to load image from memory, initialize window from an existing window, allow creating text without font/string --- include/mgl/graphics/image.h | 1 + include/mgl/graphics/sprite.h | 2 +- include/mgl/graphics/text.h | 13 +++++++++---- include/mgl/window/window.h | 1 + src/graphics/image.c | 19 +++++++++++++++++++ src/graphics/text.c | 9 +++++++-- src/window/window.c | 41 ++++++++++++++++++++++++++++++----------- 7 files changed, 68 insertions(+), 18 deletions(-) diff --git a/include/mgl/graphics/image.h b/include/mgl/graphics/image.h index b10a028..40625bb 100644 --- a/include/mgl/graphics/image.h +++ b/include/mgl/graphics/image.h @@ -21,6 +21,7 @@ struct mgl_image { }; int mgl_image_load_from_file(mgl_image *self, const char *filepath); +int mgl_image_load_from_memory(mgl_image *self, const unsigned char *data, size_t size); void mgl_image_unload(mgl_image *self); size_t mgl_image_get_size(mgl_image *self); diff --git a/include/mgl/graphics/sprite.h b/include/mgl/graphics/sprite.h index 8c84153..03f81ab 100644 --- a/include/mgl/graphics/sprite.h +++ b/include/mgl/graphics/sprite.h @@ -8,7 +8,7 @@ typedef struct mgl_context mgl_context; typedef struct mgl_texture mgl_texture; typedef struct { - mgl_texture *texture; + mgl_texture *texture; /* nullable */ mgl_color color; mgl_vec2f position; mgl_vec2f scale; diff --git a/include/mgl/graphics/text.h b/include/mgl/graphics/text.h index 33c75d0..2c2eeaf 100644 --- a/include/mgl/graphics/text.h +++ b/include/mgl/graphics/text.h @@ -8,18 +8,23 @@ typedef struct mgl_font mgl_font; typedef struct mgl_context mgl_context; typedef struct { - mgl_font *font; - const char *text; + mgl_font *font; /* nullable */ + const char *text; /* nullable */ mgl_color color; mgl_vec2f position; } mgl_text; -/* Note: keeps a reference to |text|. |text| needs to be valid as long as |self| is used. */ +/* + Note: keeps a reference to |text|. |text| needs to be valid as long as |self| is used. + |font| and |text| may be NULL. +*/ int mgl_text_init(mgl_text *self, mgl_font *font, const char *text, float x, float y); void mgl_text_deinit(mgl_text *self); -/* Note: keeps a reference to |text|. |text| needs to be valid as long as |self| is used. */ +/* Note: keeps a reference to |text|. |text| needs to be valid as long as |self| is used. |text| may be NULL. */ void mgl_text_set_string(mgl_text *self, const char *str); +/* |font| may be NULL */ +void mgl_text_set_font(mgl_text *self, mgl_font *font); void mgl_text_set_position(mgl_text *self, mgl_vec2f position); void mgl_text_set_color(mgl_text *self, mgl_color color); void mgl_text_draw(mgl_context *context, mgl_text *text); diff --git a/include/mgl/window/window.h b/include/mgl/window/window.h index c1517da..c1542b4 100644 --- a/include/mgl/window/window.h +++ b/include/mgl/window/window.h @@ -20,6 +20,7 @@ struct mgl_window { int mgl_window_create(mgl_window *self, const char *title, int width, int height); /* if |parent_window| is 0 then the root window is used */ int mgl_window_create_with_params(mgl_window *self, const char *title, int width, int height, mgl_window_handle parent_window); +int mgl_window_init_from_existing_window(mgl_window *self, mgl_window_handle existing_window); void mgl_window_deinit(mgl_window *self); void mgl_window_clear(mgl_window *self, mgl_color color); diff --git a/src/graphics/image.c b/src/graphics/image.c index 430f03a..593a3d2 100644 --- a/src/graphics/image.c +++ b/src/graphics/image.c @@ -52,6 +52,25 @@ int mgl_image_load_from_file(mgl_image *self, const char *filepath) { return 0; } +/* TODO: Ensure texture is power of 2 if the hardware doesn't support non power of two textures */ +/* TODO: Verify if source format should always be 4 components (RGBA) because apparently if its another format then opengl will internally convert it to RGBA */ +int mgl_image_load_from_memory(mgl_image *self, const unsigned char *data, size_t size) { + self->data = NULL; + self->width = 0; + self->height = 0; + + int format; + self->data = stbi_load_from_memory(data, size, &self->width, &self->height, &format, 0); + if(!self->data) { + fprintf(stderr, "Error: failed to load image from memory, error: %s\n", stbi_failure_reason()); + mgl_image_unload(self); + return -1; + } + self->format = stbi_format_to_mgl_image_format(format); + + return 0; +} + void mgl_image_unload(mgl_image *self) { if(self->data) { stbi_image_free(self->data); diff --git a/src/graphics/text.c b/src/graphics/text.c index e7b31a0..76fd852 100644 --- a/src/graphics/text.c +++ b/src/graphics/text.c @@ -18,6 +18,10 @@ void mgl_text_set_string(mgl_text *self, const char *str) { self->text = str; } +void mgl_text_set_font(mgl_text *self, mgl_font *font) { + self->font = font; +} + void mgl_text_set_position(mgl_text *self, mgl_vec2f position) { self->position = position; } @@ -43,10 +47,11 @@ static void mgl_text_draw_glyph(mgl_context *context, mgl_font_glyph *glyph, mgl /* TODO: Use opengl buffer object instead */ /* TODO: Cache texture bind to not bind texture if its already bound and do not bind texture 0 */ void mgl_text_draw(mgl_context *context, mgl_text *text) { - const char *str = text->text; - if(!str) + if(!text->text || !text->font) return; + const char *str = text->text; + mgl_font_glyph glyph; mgl_vec2f position = text->position; position.y += text->font->character_size; diff --git a/src/window/window.c b/src/window/window.c index 691a647..2e9a1ba 100644 --- a/src/window/window.c +++ b/src/window/window.c @@ -41,7 +41,7 @@ int mgl_window_create(mgl_window *self, const char *title, int width, int height return mgl_window_create_with_params(self, title, width, height, 0); } -int mgl_window_create_with_params(mgl_window *self, const char *title, int width, int height, mgl_window_handle parent_window) { +static int mgl_window_init(mgl_window *self, const char *title, int width, int height, mgl_window_handle parent_window, Window existing_window) { self->window = 0; mgl_context *context = mgl_get_context(); @@ -64,18 +64,29 @@ int mgl_window_create_with_params(mgl_window *self, const char *title, int width StructureNotifyMask; window_attr.bit_gravity = NorthWestGravity; - self->window = XCreateWindow(context->connection, parent_window, 0, 0, width, height, 0, - ((XVisualInfo*)context->visual_info)->depth, InputOutput, ((XVisualInfo*)context->visual_info)->visual, - CWColormap | CWEventMask | CWBitGravity, &window_attr); - XFreeColormap(context->connection, color_map); - if(!self->window) { - fprintf(stderr, "XCreateWindow failed\n"); - mgl_window_deinit(self); - return -1; + if(existing_window) { + if(!XChangeWindowAttributes(context->connection, existing_window, CWColormap | CWEventMask | CWBitGravity, &window_attr)) { + fprintf(stderr, "XChangeWindowAttributes failed\n"); + XFreeColormap(context->connection, color_map); + return -1; + } + XFreeColormap(context->connection, color_map); + self->window = existing_window; + } else { + self->window = XCreateWindow(context->connection, parent_window, 0, 0, width, height, 0, + ((XVisualInfo*)context->visual_info)->depth, InputOutput, ((XVisualInfo*)context->visual_info)->visual, + CWColormap | CWEventMask | CWBitGravity, &window_attr); + XFreeColormap(context->connection, color_map); + if(!self->window) { + fprintf(stderr, "XCreateWindow failed\n"); + mgl_window_deinit(self); + return -1; + } + + XStoreName(context->connection, self->window, title); + XMapWindow(context->connection, self->window); } - XStoreName(context->connection, self->window, title); - XMapWindow(context->connection, self->window); XFlush(context->connection); /* TODO: Switch current when rendering to another window, and set current to NULL when destroying the currently selected context */ @@ -102,6 +113,14 @@ int mgl_window_create_with_params(mgl_window *self, const char *title, int width return 0; } +int mgl_window_create_with_params(mgl_window *self, const char *title, int width, int height, mgl_window_handle parent_window) { + return mgl_window_init(self, title, width, height, parent_window, None); +} + +int mgl_window_init_from_existing_window(mgl_window *self, mgl_window_handle existing_window) { + return mgl_window_init(self, "", 0, 0, 0, existing_window); +} + void mgl_window_deinit(mgl_window *self) { mgl_context *context = mgl_get_context(); if(self->window) { -- cgit v1.2.3