summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorJaakko Keränen <jaakko.keranen@iki.fi>2021-08-20 09:07:09 +0300
committerJaakko Keränen <jaakko.keranen@iki.fi>2021-08-20 09:07:09 +0300
commite9e496ffb64d83a55162d38ffc6d87a364bb6a95 (patch)
treea8a76c8bf63b24347e5d09582319db5eca4e7d88 /src
parent4e62a21cea5781fc91ec5ef22710e0fe19badb3c (diff)
Added WebP decoding using libwebp
Diffstat (limited to 'src')
-rw-r--r--src/gmdocument.c5
-rw-r--r--src/gmutil.c54
-rw-r--r--src/gmutil.h1
-rw-r--r--src/media.c16
-rw-r--r--src/ui/documentwidget.c30
5 files changed, 74 insertions, 32 deletions
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
240 iString *path = newRange_String(parts.path); 240 iString *path = newRange_String(parts.path);
241 if (endsWithCase_String(path, ".gif") || endsWithCase_String(path, ".jpg") || 241 if (endsWithCase_String(path, ".gif") || endsWithCase_String(path, ".jpg") ||
242 endsWithCase_String(path, ".jpeg") || endsWithCase_String(path, ".png") || 242 endsWithCase_String(path, ".jpeg") || endsWithCase_String(path, ".png") ||
243 endsWithCase_String(path, ".tga") || endsWithCase_String(path, ".psd") || 243 endsWithCase_String(path, ".tga") || endsWithCase_String(path, ".psd") ||
244#if defined (LAGRANGE_ENABLE_WEBP)
245 endsWithCase_String(path, ".webp") ||
246#endif
244 endsWithCase_String(path, ".hdr") || endsWithCase_String(path, ".pic")) { 247 endsWithCase_String(path, ".hdr") || endsWithCase_String(path, ".pic")) {
245 link->flags |= imageFileExtension_GmLinkFlag; 248 link->flags |= imageFileExtension_GmLinkFlag;
246 } 249 }
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) {
511 return NULL; 511 return NULL;
512} 512}
513 513
514const char *mediaType_Path(const iString *path) { 514const char *mediaTypeFromFileExtension_String(const iString *d) {
515 if (endsWithCase_String(path, ".gmi") || endsWithCase_String(path, ".gemini")) { 515 if (endsWithCase_String(d, ".gmi") || endsWithCase_String(d, ".gemini")) {
516 return "text/gemini; charset=utf-8"; 516 return "text/gemini; charset=utf-8";
517 } 517 }
518 else if (endsWithCase_String(path, ".pem")) { 518 else if (endsWithCase_String(d, ".pem")) {
519 return "application/x-pem-file"; 519 return "application/x-pem-file";
520 } 520 }
521 else if (endsWithCase_String(path, ".zip")) { 521 else if (endsWithCase_String(d, ".zip")) {
522 return "application/zip"; 522 return "application/zip";
523 } 523 }
524 else if (endsWithCase_String(path, ".gpub")) { 524 else if (endsWithCase_String(d, ".gpub")) {
525 return "application/gpub+zip"; 525 return "application/gpub+zip";
526 } 526 }
527 else if (endsWithCase_String(path, ".xml")) { 527 else if (endsWithCase_String(d, ".xml")) {
528 return "text/xml"; 528 return "text/xml";
529 } 529 }
530 else if (endsWithCase_String(path, ".png")) { 530 else if (endsWithCase_String(d, ".png")) {
531 return "image/png"; 531 return "image/png";
532 } 532 }
533 else if (endsWithCase_String(path, ".jpg") || endsWithCase_String(path, ".jpeg")) { 533 else if (endsWithCase_String(d, ".webp")) {
534 return "image/webp";
535 }
536 else if (endsWithCase_String(d, ".jpg") || endsWithCase_String(d, ".jpeg")) {
534 return "image/jpeg"; 537 return "image/jpeg";
535 } 538 }
536 else if (endsWithCase_String(path, ".gif")) { 539 else if (endsWithCase_String(d, ".gif")) {
537 return "image/gif"; 540 return "image/gif";
538 } 541 }
539 else if (endsWithCase_String(path, ".wav")) { 542 else if (endsWithCase_String(d, ".wav")) {
540 return "audio/wave"; 543 return "audio/wave";
541 } 544 }
542 else if (endsWithCase_String(path, ".ogg")) { 545 else if (endsWithCase_String(d, ".ogg")) {
543 return "audio/ogg"; 546 return "audio/ogg";
544 } 547 }
545 else if (endsWithCase_String(path, ".mp3")) { 548 else if (endsWithCase_String(d, ".mp3")) {
546 return "audio/mpeg"; 549 return "audio/mpeg";
547 } 550 }
548 else if (endsWithCase_String(path, ".mid")) { 551 else if (endsWithCase_String(d, ".mid")) {
549 return "audio/midi"; 552 return "audio/midi";
550 } 553 }
551 else if (endsWithCase_String(path, ".txt") || 554 else if (endsWithCase_String(d, ".txt") ||
552 endsWithCase_String(path, ".md") || 555 endsWithCase_String(d, ".md") ||
553 endsWithCase_String(path, ".c") || 556 endsWithCase_String(d, ".c") ||
554 endsWithCase_String(path, ".h") || 557 endsWithCase_String(d, ".h") ||
555 endsWithCase_String(path, ".cc") || 558 endsWithCase_String(d, ".cc") ||
556 endsWithCase_String(path, ".hh") || 559 endsWithCase_String(d, ".hh") ||
557 endsWithCase_String(path, ".cpp") || 560 endsWithCase_String(d, ".cpp") ||
558 endsWithCase_String(path, ".hpp")) { 561 endsWithCase_String(d, ".hpp")) {
559 return "text/plain"; 562 return "text/plain";
560 } 563 }
561 const char *mtype = "application/octet-stream"; 564 return "application/octet-stream";
565}
566
567const char *mediaType_Path(const iString *path) {
568 const char *mtype = mediaTypeFromFileExtension_String(path);
569 if (iCmpStr(mtype, "application/octet-stream")) {
570 return mtype; /* extension recognized */
571 }
562 /* If the file is reasonably small and looks like UTF-8, we'll display it as text/plain. */ 572 /* If the file is reasonably small and looks like UTF-8, we'll display it as text/plain. */
563 if (fileExists_FileInfo(path) && fileSize_FileInfo(path) <= 5000000) { 573 if (fileExists_FileInfo(path) && fileSize_FileInfo(path) <= 5000000) {
564 iFile *f = new_File(path); 574 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 *);
133const iString * canonicalUrl_String (const iString *); 133const iString * canonicalUrl_String (const iString *);
134 134
135const char * mediaType_Path (const iString *path); 135const char * mediaType_Path (const iString *path);
136const char * mediaTypeFromFileExtension_String (const iString *);
136iRangecc mediaTypeWithoutParameters_Rangecc (iRangecc mime); 137iRangecc mediaTypeWithoutParameters_Rangecc (iRangecc mime);
137 138
138const iString * findContainerArchive_Path (const iString *path); 139const 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. */
30#include "stb_image.h" 30#include "stb_image.h"
31#include "stb_image_resize.h" 31#include "stb_image_resize.h"
32 32
33#if defined (LAGRANGE_ENABLE_WEBP)
34# include <webp/decode.h>
35#endif
36
33#include <the_Foundation/file.h> 37#include <the_Foundation/file.h>
34#include <the_Foundation/ptrarray.h> 38#include <the_Foundation/ptrarray.h>
35#include <SDL_hints.h> 39#include <SDL_hints.h>
@@ -86,8 +90,16 @@ void deinit_GmImage(iGmImage *d) {
86void makeTexture_GmImage(iGmImage *d) { 90void makeTexture_GmImage(iGmImage *d) {
87 iBlock *data = &d->partialData; 91 iBlock *data = &d->partialData;
88 d->numBytes = size_Block(data); 92 d->numBytes = size_Block(data);
89 uint8_t *imgData = stbi_load_from_memory( 93 uint8_t *imgData = NULL;
90 constData_Block(data), size_Block(data), &d->size.x, &d->size.y, NULL, 4); 94 if (cmp_String(&d->props.mime, "image/webp") == 0) {
95#if defined (LAGRANGE_ENABLE_WEBP)
96 imgData = WebPDecodeRGBA(constData_Block(data), size_Block(data), &d->size.x, &d->size.y);
97#endif
98 }
99 else {
100 imgData = stbi_load_from_memory(
101 constData_Block(data), size_Block(data), &d->size.x, &d->size.y, NULL, 4);
102 }
91 if (!imgData) { 103 if (!imgData) {
92 d->size = zero_I2(); 104 d->size = zero_I2();
93 d->texture = NULL; 105 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
1168 iString *key = collectNew_String(); 1168 iString *key = collectNew_String();
1169 toString_Sym(SDLK_s, KMOD_PRIMARY, key); 1169 toString_Sym(SDLK_s, KMOD_PRIMARY, key);
1170 appendFormat_String(src, "\n```\n%s\n```\n", cstr_String(meta)); 1170 appendFormat_String(src, "\n```\n%s\n```\n", cstr_String(meta));
1171 makeFooterButtons_DocumentWidget_( 1171 const char *mtype = mediaTypeFromFileExtension_String(d->mod.url);
1172 d, 1172 iArray items;
1173 (iMenuItem[]){ { translateCStr_Lang(download_Icon " " saveToDownloads_Label), 1173 init_Array(&items, sizeof(iMenuItem));
1174 0, 1174 if (iCmpStr(mtype, "application/octet-stream")) {
1175 0, 1175 pushBack_Array(
1176 "document.save" } }, 1176 &items,
1177 1); 1177 &(iMenuItem){ translateCStr_Lang(format_CStr("View as \"%s\"", mtype)),
1178 SDLK_RETURN,
1179 0,
1180 format_CStr("document.setmediatype mime:%s", mtype) });
1181 }
1182 pushBack_Array(
1183 &items,
1184 &(iMenuItem){ translateCStr_Lang(download_Icon " " saveToDownloads_Label),
1185 0,
1186 0,
1187 "document.save" });
1188 makeFooterButtons_DocumentWidget_(d, data_Array(&items), size_Array(&items));
1189 deinit_Array(&items);
1178 break; 1190 break;
1179 } 1191 }
1180 default: 1192 default:
@@ -3176,6 +3188,10 @@ static iBool handleCommand_DocumentWidget_(iDocumentWidget *d, const char *cmd)
3176 document_App() == d) { 3188 document_App() == d) {
3177 return handleSwipe_DocumentWidget_(d, cmd); 3189 return handleSwipe_DocumentWidget_(d, cmd);
3178 } 3190 }
3191 else if (equal_Command(cmd, "document.setmediatype") && document_App() == d) {
3192 setUrlAndSource_DocumentWidget(d, d->mod.url, string_Command(cmd, "mime"), &d->sourceContent);
3193 return iTrue;
3194 }
3179 return iFalse; 3195 return iFalse;
3180} 3196}
3181 3197