From e9e496ffb64d83a55162d38ffc6d87a364bb6a95 Mon Sep 17 00:00:00 2001 From: Jaakko Keränen Date: Fri, 20 Aug 2021 09:07:09 +0300 Subject: Added WebP decoding using libwebp --- src/gmdocument.c | 5 ++++- src/gmutil.c | 54 +++++++++++++++++++++++++++++-------------------- src/gmutil.h | 1 + src/media.c | 16 +++++++++++++-- src/ui/documentwidget.c | 30 ++++++++++++++++++++------- 5 files changed, 74 insertions(+), 32 deletions(-) (limited to 'src') diff --git a/src/gmdocument.c b/src/gmdocument.c index 6ed628de..75f6f06b 100644 --- a/src/gmdocument.c +++ b/src/gmdocument.c @@ -240,7 +240,10 @@ static iRangecc addLink_GmDocument_(iGmDocument *d, iRangecc line, iGmLinkId *li iString *path = newRange_String(parts.path); if (endsWithCase_String(path, ".gif") || endsWithCase_String(path, ".jpg") || endsWithCase_String(path, ".jpeg") || endsWithCase_String(path, ".png") || - endsWithCase_String(path, ".tga") || endsWithCase_String(path, ".psd") || + endsWithCase_String(path, ".tga") || endsWithCase_String(path, ".psd") || +#if defined (LAGRANGE_ENABLE_WEBP) + endsWithCase_String(path, ".webp") || +#endif endsWithCase_String(path, ".hdr") || endsWithCase_String(path, ".pic")) { link->flags |= imageFileExtension_GmLinkFlag; } diff --git a/src/gmutil.c b/src/gmutil.c index 9bd74ee0..d547d27d 100644 --- a/src/gmutil.c +++ b/src/gmutil.c @@ -511,54 +511,64 @@ const iString *findContainerArchive_Path(const iString *path) { return NULL; } -const char *mediaType_Path(const iString *path) { - if (endsWithCase_String(path, ".gmi") || endsWithCase_String(path, ".gemini")) { +const char *mediaTypeFromFileExtension_String(const iString *d) { + if (endsWithCase_String(d, ".gmi") || endsWithCase_String(d, ".gemini")) { return "text/gemini; charset=utf-8"; } - else if (endsWithCase_String(path, ".pem")) { + else if (endsWithCase_String(d, ".pem")) { return "application/x-pem-file"; } - else if (endsWithCase_String(path, ".zip")) { + else if (endsWithCase_String(d, ".zip")) { return "application/zip"; } - else if (endsWithCase_String(path, ".gpub")) { + else if (endsWithCase_String(d, ".gpub")) { return "application/gpub+zip"; } - else if (endsWithCase_String(path, ".xml")) { + else if (endsWithCase_String(d, ".xml")) { return "text/xml"; } - else if (endsWithCase_String(path, ".png")) { + else if (endsWithCase_String(d, ".png")) { return "image/png"; } - else if (endsWithCase_String(path, ".jpg") || endsWithCase_String(path, ".jpeg")) { + else if (endsWithCase_String(d, ".webp")) { + return "image/webp"; + } + else if (endsWithCase_String(d, ".jpg") || endsWithCase_String(d, ".jpeg")) { return "image/jpeg"; } - else if (endsWithCase_String(path, ".gif")) { + else if (endsWithCase_String(d, ".gif")) { return "image/gif"; } - else if (endsWithCase_String(path, ".wav")) { + else if (endsWithCase_String(d, ".wav")) { return "audio/wave"; } - else if (endsWithCase_String(path, ".ogg")) { + else if (endsWithCase_String(d, ".ogg")) { return "audio/ogg"; } - else if (endsWithCase_String(path, ".mp3")) { + else if (endsWithCase_String(d, ".mp3")) { return "audio/mpeg"; } - else if (endsWithCase_String(path, ".mid")) { + else if (endsWithCase_String(d, ".mid")) { return "audio/midi"; } - else if (endsWithCase_String(path, ".txt") || - endsWithCase_String(path, ".md") || - endsWithCase_String(path, ".c") || - endsWithCase_String(path, ".h") || - endsWithCase_String(path, ".cc") || - endsWithCase_String(path, ".hh") || - endsWithCase_String(path, ".cpp") || - endsWithCase_String(path, ".hpp")) { + else if (endsWithCase_String(d, ".txt") || + endsWithCase_String(d, ".md") || + endsWithCase_String(d, ".c") || + endsWithCase_String(d, ".h") || + endsWithCase_String(d, ".cc") || + endsWithCase_String(d, ".hh") || + endsWithCase_String(d, ".cpp") || + endsWithCase_String(d, ".hpp")) { return "text/plain"; } - const char *mtype = "application/octet-stream"; + return "application/octet-stream"; +} + +const char *mediaType_Path(const iString *path) { + const char *mtype = mediaTypeFromFileExtension_String(path); + if (iCmpStr(mtype, "application/octet-stream")) { + return mtype; /* extension recognized */ + } /* If the file is reasonably small and looks like UTF-8, we'll display it as text/plain. */ if (fileExists_FileInfo(path) && fileSize_FileInfo(path) <= 5000000) { iFile *f = new_File(path); diff --git a/src/gmutil.h b/src/gmutil.h index f8491781..3c10d45b 100644 --- a/src/gmutil.h +++ b/src/gmutil.h @@ -133,6 +133,7 @@ const iString * withSpacesEncoded_String(const iString *); const iString * canonicalUrl_String (const iString *); const char * mediaType_Path (const iString *path); +const char * mediaTypeFromFileExtension_String (const iString *); iRangecc mediaTypeWithoutParameters_Rangecc (iRangecc mime); const iString * findContainerArchive_Path (const iString *path); diff --git a/src/media.c b/src/media.c index eb4a8311..5240ab5d 100644 --- a/src/media.c +++ b/src/media.c @@ -30,6 +30,10 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include "stb_image.h" #include "stb_image_resize.h" +#if defined (LAGRANGE_ENABLE_WEBP) +# include +#endif + #include #include #include @@ -86,8 +90,16 @@ void deinit_GmImage(iGmImage *d) { void makeTexture_GmImage(iGmImage *d) { iBlock *data = &d->partialData; d->numBytes = size_Block(data); - uint8_t *imgData = stbi_load_from_memory( - constData_Block(data), size_Block(data), &d->size.x, &d->size.y, NULL, 4); + uint8_t *imgData = NULL; + if (cmp_String(&d->props.mime, "image/webp") == 0) { +#if defined (LAGRANGE_ENABLE_WEBP) + imgData = WebPDecodeRGBA(constData_Block(data), size_Block(data), &d->size.x, &d->size.y); +#endif + } + else { + imgData = stbi_load_from_memory( + constData_Block(data), size_Block(data), &d->size.x, &d->size.y, NULL, 4); + } if (!imgData) { d->size = zero_I2(); d->texture = NULL; diff --git a/src/ui/documentwidget.c b/src/ui/documentwidget.c index 3f655db5..83f38dee 100644 --- a/src/ui/documentwidget.c +++ b/src/ui/documentwidget.c @@ -1168,13 +1168,25 @@ static void showErrorPage_DocumentWidget_(iDocumentWidget *d, enum iGmStatusCode iString *key = collectNew_String(); toString_Sym(SDLK_s, KMOD_PRIMARY, key); appendFormat_String(src, "\n```\n%s\n```\n", cstr_String(meta)); - makeFooterButtons_DocumentWidget_( - d, - (iMenuItem[]){ { translateCStr_Lang(download_Icon " " saveToDownloads_Label), - 0, - 0, - "document.save" } }, - 1); + const char *mtype = mediaTypeFromFileExtension_String(d->mod.url); + iArray items; + init_Array(&items, sizeof(iMenuItem)); + if (iCmpStr(mtype, "application/octet-stream")) { + pushBack_Array( + &items, + &(iMenuItem){ translateCStr_Lang(format_CStr("View as \"%s\"", mtype)), + SDLK_RETURN, + 0, + format_CStr("document.setmediatype mime:%s", mtype) }); + } + pushBack_Array( + &items, + &(iMenuItem){ translateCStr_Lang(download_Icon " " saveToDownloads_Label), + 0, + 0, + "document.save" }); + makeFooterButtons_DocumentWidget_(d, data_Array(&items), size_Array(&items)); + deinit_Array(&items); break; } default: @@ -3176,6 +3188,10 @@ static iBool handleCommand_DocumentWidget_(iDocumentWidget *d, const char *cmd) document_App() == d) { return handleSwipe_DocumentWidget_(d, cmd); } + else if (equal_Command(cmd, "document.setmediatype") && document_App() == d) { + setUrlAndSource_DocumentWidget(d, d->mod.url, string_Command(cmd, "mime"), &d->sourceContent); + return iTrue; + } return iFalse; } -- cgit v1.2.3