Lagrange [release]
Media: Images not processed until data is complete
[1mdiff --git a/src/media.c b/src/media.c[m
[1mindex ddf5d45f..253893fc 100644[m
[1m--- a/src/media.c[m
[1m+++ b/src/media.c[m
[36m@@ -54,14 +54,29 @@[m [miDeclareType(GmImage)[m
[m
struct Impl_GmImage {[m
iGmMediaProps props;[m
[31m- iInt2 size;[m
[31m- size_t numBytes;[m
[31m- SDL_Texture *texture;[m
[32m+[m[32m iBlock partialData; /* cleared when image is converted to texture */[m
[32m+[m[32m iInt2 size;[m
[32m+[m[32m size_t numBytes;[m
[32m+[m[32m SDL_Texture * texture;[m
};[m
[m
void init_GmImage(iGmImage *d, const iBlock *data) {[m
init_GmMediaProps_(&d->props);[m
[31m- d->numBytes = size_Block(data);[m
[32m+[m[32m initCopy_Block(&d->partialData, data);[m
[32m+[m[32m d->size = zero_I2();[m
[32m+[m[32m d->numBytes = 0;[m
[32m+[m[32m d->texture = NULL;[m
[32m+[m[32m}[m
[32m+[m
[32m+[m[32mvoid deinit_GmImage(iGmImage *d) {[m
[32m+[m[32m deinit_Block(&d->partialData);[m
[32m+[m[32m SDL_DestroyTexture(d->texture);[m
[32m+[m[32m deinit_GmMediaProps_(&d->props);[m
[32m+[m[32m}[m
[32m+[m
[32m+[m[32mvoid makeTexture_GmImage(iGmImage *d) {[m
[32m+[m[32m iBlock *data = &d->partialData;[m
[32m+[m[32m d->numBytes = size_Block(data);[m
uint8_t *imgData = stbi_load_from_memory([m
constData_Block(data), size_Block(data), &d->size.x, &d->size.y, NULL, 4);[m
if (!imgData) {[m
[36m@@ -69,6 +84,8 @@[m [mvoid init_GmImage(iGmImage *d, const iBlock *data) {[m
d->texture = NULL;[m
}[m
else {[m
[32m+[m[32m /* TODO: Save some memory by checking if the alpha channel is actually in use. */[m
[32m+[m[32m /* TODO: Resize down to min(maximum texture size, window size). */[m
SDL_Surface *surface = SDL_CreateRGBSurfaceWithFormatFrom([m
imgData, d->size.x, d->size.y, 32, d->size.x * 4, SDL_PIXELFORMAT_ABGR8888);[m
/* TODO: In multiwindow case, all windows must have the same shared renderer?[m
[36m@@ -78,11 +95,7 @@[m [mvoid init_GmImage(iGmImage *d, const iBlock *data) {[m
SDL_FreeSurface(surface);[m
stbi_image_free(imgData);[m
}[m
[31m-}[m
[31m-[m
[31m-void deinit_GmImage(iGmImage *d) {[m
[31m- SDL_DestroyTexture(d->texture);[m
[31m- deinit_GmMediaProps_(&d->props);[m
[32m+[m[32m clear_Block(data);[m
}[m
[m
iDefineTypeConstructionArgs(GmImage, (const iBlock *data), data)[m
[36m@@ -144,15 +157,20 @@[m [mvoid setData_Media(iMedia *d, iGmLinkId linkId, const iString *mime, const iBloc[m
const iBool isPartial = (flags & partialData_MediaFlag) != 0;[m
const iBool allowHide = (flags & allowHide_MediaFlag) != 0;[m
const iBool isDeleting = (!mime || !data);[m
[31m- iMediaId existing = findLinkImage_Media(d, linkId);[m
[32m+[m[32m iMediaId existing = findLinkImage_Media(d, linkId);[m[41m [m
if (existing) {[m
[32m+[m[32m iGmImage *img;[m
if (isDeleting) {[m
[31m- iGmImage *img;[m
take_PtrArray(&d->images, existing - 1, (void **) &img);[m
delete_GmImage(img);[m
}[m
else {[m
[31m- iAssert(isDeleting); /* images cannot be modified once set */[m
[32m+[m[32m img = at_PtrArray(&d->images, existing - 1);[m
[32m+[m[32m iAssert(equal_String(&img->props.mime, mime)); /* MIME cannot change */[m
[32m+[m[32m set_Block(&img->partialData, data);[m
[32m+[m[32m if (!isPartial) {[m
[32m+[m[32m makeTexture_GmImage(img);[m
[32m+[m[32m }[m
}[m
}[m
else if ((existing = findLinkAudio_Media(d, linkId)) != 0) {[m
[36m@@ -177,16 +195,13 @@[m [mvoid setData_Media(iMedia *d, iGmLinkId linkId, const iString *mime, const iBloc[m
else if (!isDeleting) {[m
if (startsWith_String(mime, "image/")) {[m
/* Copy the image to a texture. */[m
[31m- /* TODO: Resize down to min(maximum texture size, window size). */[m
iGmImage *img = new_GmImage(data);[m
[31m- img->props.linkId = linkId; /* TODO: use a hash? */[m
[32m+[m[32m img->props.linkId = linkId; /* TODO: use a hash? */[m
img->props.isPermanent = !allowHide;[m
set_String(&img->props.mime, mime);[m
[31m- if (img->texture) {[m
[31m- pushBack_PtrArray(&d->images, img);[m
[31m- }[m
[31m- else {[m
[31m- delete_GmImage(img);[m
[32m+[m[32m pushBack_PtrArray(&d->images, img);[m
[32m+[m[32m if (!isPartial) {[m
[32m+[m[32m makeTexture_GmImage(img);[m
}[m
}[m
else if (startsWith_String(mime, "audio/")) {[m