aboutsummaryrefslogtreecommitdiff
path: root/src/image.c
diff options
context:
space:
mode:
authorHarry Jeffery <harry@exec64.co.uk>2019-06-15 14:28:29 +0100
committerHarry Jeffery <harry@exec64.co.uk>2019-07-03 20:50:19 +0100
commit7c7dc660e587eac1aa3c8b3405eba95ba558e682 (patch)
tree81d12d560b60d397be23c7d132e32a5de30e409a /src/image.c
parent20e9d23b82f55a751c3cf1166cb59ef26775ee00 (diff)
downloadimv-7c7dc660e587eac1aa3c8b3405eba95ba558e682.tar.gz
Big glfw refactor
I did a lot of this in a very ad-hoc fashion with no proper commit history. As such, the kindest thing to do seemed to be to just squash it into this one commit.
Diffstat (limited to 'src/image.c')
-rw-r--r--src/image.c182
1 files changed, 46 insertions, 136 deletions
diff --git a/src/image.c b/src/image.c
index e57d2c9..f4df7c9 100644
--- a/src/image.c
+++ b/src/image.c
@@ -1,170 +1,80 @@
#include "image.h"
-#include "log.h"
-#include <stdbool.h>
+#include "bitmap.h"
struct imv_image {
- int width; /* width of the image overall */
- int height; /* height of the image overall */
- int num_chunks; /* number of chunks allocated */
- SDL_Texture **chunks; /* array of chunks */
- int num_chunks_wide; /* number of chunks per row of the image */
- int num_chunks_tall; /* number of chunks per column of the image */
- int chunk_width; /* chunk width */
- int chunk_height; /* chunk height */
- int last_chunk_width; /* width of rightmost chunk */
- int last_chunk_height; /* height of bottommost chunk */
- SDL_Renderer *renderer; /* SDL renderer to draw to */
+ int width;
+ int height;
+ struct imv_bitmap *bitmap;
+ #ifdef IMV_BACKEND_LIBRSVG
+ RsvgHandle *svg;
+ #endif
};
-struct imv_image *imv_image_create(SDL_Renderer *r)
+struct imv_image *imv_image_create_from_bitmap(struct imv_bitmap *bmp)
{
- struct imv_image *image = malloc(sizeof *image);
- memset(image, 0, sizeof(struct imv_image));
- image->renderer = r;
-
- SDL_RendererInfo ri;
- SDL_GetRendererInfo(r, &ri);
- image->chunk_width = ri.max_texture_width != 0 ? ri.max_texture_width : 4096;
- image->chunk_height = ri.max_texture_height != 0 ? ri.max_texture_height : 4096;
+ struct imv_image *image = calloc(1, sizeof *image);
+ image->width = bmp->width;
+ image->height = bmp->height;
+ image->bitmap = bmp;
return image;
}
-void imv_image_free(struct imv_image *image)
+#ifdef IMV_BACKEND_LIBRSVG
+struct imv_image *imv_image_create_from_svg(RsvgHandle *handle)
{
- if(!image) {
- return;
- }
- if(image->num_chunks > 0) {
- for(int i = 0; i < image->num_chunks; ++i) {
- SDL_DestroyTexture(image->chunks[i]);
- }
- free(image->chunks);
- image->num_chunks = 0;
- image->chunks = NULL;
- image->renderer = NULL;
- }
- free(image);
-}
+ struct imv_image *image = calloc(1, sizeof *image);
+ image->svg = handle;
-static int convert_pixelformat(enum imv_pixelformat fmt)
-{
- if (fmt == IMV_ARGB) {
- return SDL_PIXELFORMAT_ARGB8888;
- } else if (fmt == IMV_ABGR) {
- return SDL_PIXELFORMAT_ABGR8888;
- } else {
- imv_log(IMV_WARNING, "Unknown pixel format. Defaulting to ARGB\n");
- return SDL_PIXELFORMAT_ARGB8888;
- }
+ RsvgDimensionData dim;
+ rsvg_handle_get_dimensions(handle, &dim);
+ image->width = dim.width;
+ image->height = dim.height;
+ return image;
}
+#endif
-int imv_image_set_bitmap(struct imv_image *image, struct imv_bitmap *bmp)
+void imv_image_free(struct imv_image *image)
{
- image->width = bmp->width;
- image->height = bmp->height;
-
- /* figure out how many chunks are needed, and create them */
- if(image->num_chunks > 0) {
- for(int i = 0; i < image->num_chunks; ++i) {
- SDL_DestroyTexture(image->chunks[i]);
- }
- free(image->chunks);
- }
-
- image->num_chunks_wide = 1 + image->width / image->chunk_width;
- image->num_chunks_tall = 1 + image->height / image->chunk_height;
-
- image->last_chunk_width = image->width % image->chunk_width;
- image->last_chunk_height = image->height % image->chunk_height;
-
- if(image->last_chunk_width == 0) {
- image->last_chunk_width = image->chunk_width;
- }
- if(image->last_chunk_height == 0) {
- image->last_chunk_height = image->chunk_height;
+ if (!image) {
+ return;
}
- image->num_chunks = image->num_chunks_wide * image->num_chunks_tall;
- image->chunks = malloc(sizeof(SDL_Texture*) * image->num_chunks);
-
- const int format = convert_pixelformat(bmp->format);
- size_t failed_at = -1;
- for(int y = 0; y < image->num_chunks_tall; ++y) {
- for(int x = 0; x < image->num_chunks_wide; ++x) {
- const bool is_last_h_chunk = (x == image->num_chunks_wide - 1);
- const bool is_last_v_chunk = (y == image->num_chunks_tall - 1);
- const size_t index = x + y * image->num_chunks_wide;
- image->chunks[index] =
- SDL_CreateTexture(image->renderer,
- format,
- SDL_TEXTUREACCESS_STATIC,
- is_last_h_chunk ? image->last_chunk_width : image->chunk_width,
- is_last_v_chunk ? image->last_chunk_height : image->chunk_height);
- SDL_SetTextureBlendMode(image->chunks[index],
- SDL_BLENDMODE_BLEND);
- if (image->chunks[index] == NULL) {
- failed_at = x + y * image->num_chunks_wide;
- break;
- }
- }
+ if (image->bitmap) {
+ imv_bitmap_free(image->bitmap);
}
- if (failed_at != (size_t)-1) {
- for (size_t i = 0; i < failed_at; ++i) {
- SDL_DestroyTexture(image->chunks[i]);
- }
- free(image->chunks);
- image->num_chunks = 0;
- image->chunks = NULL;
- return 1;
+#ifdef IMV_BACKEND_LIBRSVG
+ if (image->svg) {
+ GError *error = NULL;
+ rsvg_handle_close(image->svg, &error);
}
+#endif
- for (int y = 0; y < image->num_chunks_tall; ++y) {
- for (int x = 0; x < image->num_chunks_wide; ++x) {
- ptrdiff_t offset = 4 * x * image->chunk_width +
- y * 4 * image->width * image->chunk_height;
- unsigned char* addr = bmp->data + offset;
- SDL_UpdateTexture(image->chunks[x + y * image->num_chunks_wide],
- NULL, addr, 4 * image->width);
- }
- }
+ free(image);
+}
- return 0;
+int imv_image_width(const struct imv_image *image)
+{
+ return image ? image->width : 0;
}
-void imv_image_draw(struct imv_image *image, int bx, int by, double scale)
+int imv_image_height(const struct imv_image *image)
{
- int offset_x = 0;
- int offset_y = 0;
- for(int y = 0; y < image->num_chunks_tall; ++y) {
- for(int x = 0; x < image->num_chunks_wide; ++x) {
- int img_w, img_h;
- SDL_QueryTexture(image->chunks[x + y * image->num_chunks_wide], NULL, NULL,
- &img_w, &img_h);
- SDL_Rect view_area = {
- bx + offset_x,
- by + offset_y,
- img_w * scale,
- img_h * scale
- };
- SDL_RenderCopy(image->renderer,
- image->chunks[x + y * image->num_chunks_wide], NULL, &view_area);
- offset_x += image->chunk_width * scale;
- }
- offset_x = 0;
- offset_y += image->chunk_height * scale;
- }
+ return image ? image->height : 0;
}
-int imv_image_width(const struct imv_image *image)
+/* Non-public functions, only used by imv_canvas */
+struct imv_bitmap *imv_image_get_bitmap(const struct imv_image *image)
{
- return image->width;
+ return image->bitmap;
}
-int imv_image_height(const struct imv_image *image)
+#ifdef IMV_BACKEND_LIBRSVG
+RsvgHandle *imv_image_get_svg(const struct imv_image *image)
{
- return image->height;
+ return image->svg;
}
+#endif
/* vim:set ts=2 sts=2 sw=2 et: */