mirror of
https://github.com/rkd77/elinks.git
synced 2025-04-18 00:47:36 -04:00
[sixel] messy code to load sixel images
memfd_create is not portable, but I don't want to modify libsixel code.
This commit is contained in:
parent
9809c60d1d
commit
b718f8955e
@ -415,6 +415,7 @@ done_document(struct document *document)
|
||||
while (!list_empty(document->images)) {
|
||||
delete_image((struct image *)document->images.next);
|
||||
}
|
||||
free_uri_list(&document->image_uris);
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_CSS
|
||||
|
@ -313,6 +313,7 @@ struct document {
|
||||
enum clipboard_status clipboard_status;
|
||||
#ifdef CONFIG_LIBSIXEL
|
||||
LIST_OF(struct image) images;
|
||||
struct uri_list image_uris;
|
||||
#endif
|
||||
};
|
||||
|
||||
|
@ -26,6 +26,7 @@
|
||||
#include "bfu/listmenu.h"
|
||||
#include "bfu/menu.h"
|
||||
#include "bookmarks/bookmarks.h"
|
||||
#include "cache/cache.h"
|
||||
#include "config/options.h"
|
||||
#include "config/kbdbind.h"
|
||||
#include "document/html/frames.h"
|
||||
@ -235,25 +236,60 @@ html_img_sixel(struct html_context *html_context, char *a,
|
||||
if (!html_context->options->sixel || !html_context->document) {
|
||||
return;
|
||||
}
|
||||
unsigned char *data = NULL;
|
||||
int datalen = 0;
|
||||
char *elsix = get_attr_val(a, "elsix", html_context->doc_cp);
|
||||
|
||||
if (!elsix) {
|
||||
return;
|
||||
char *url = get_attr_val(a, "src", html_context->doc_cp);
|
||||
|
||||
if (!url) {
|
||||
return;
|
||||
}
|
||||
char *url2 = join_urls(html_context->base_href, url);
|
||||
|
||||
if (url2) {
|
||||
struct uri *uri = get_uri(url2, URI_BASE);
|
||||
|
||||
if (uri) {
|
||||
struct cache_entry *cached = get_redirected_cache_entry(uri);
|
||||
|
||||
if (cached) {
|
||||
struct fragment *fragment = get_cache_fragment(cached);
|
||||
|
||||
if (fragment) {
|
||||
data = el_sixel_get_image(fragment->data, fragment->length);
|
||||
}
|
||||
}
|
||||
if (!data) {
|
||||
html_context->special_f(html_context, SP_IMAGE, uri);
|
||||
}
|
||||
done_uri(uri);
|
||||
}
|
||||
mem_free(url2);
|
||||
}
|
||||
mem_free(url);
|
||||
if (data) {
|
||||
datalen = strlen(data);
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
}
|
||||
struct string pixels;
|
||||
|
||||
if (!init_string(&pixels)) {
|
||||
mem_free(elsix);
|
||||
mem_free_if(elsix);
|
||||
return;
|
||||
}
|
||||
int datalen;
|
||||
unsigned char *data = base64_decode_bin((const unsigned char *)elsix, strlen(elsix), &datalen);
|
||||
if (!datalen) {
|
||||
data = base64_decode_bin((const unsigned char *)elsix, strlen(elsix), &datalen);
|
||||
|
||||
mem_free(elsix);
|
||||
mem_free(elsix);
|
||||
|
||||
if (!data) {
|
||||
done_string(&pixels);
|
||||
return;
|
||||
if (!data) {
|
||||
done_string(&pixels);
|
||||
return;
|
||||
}
|
||||
}
|
||||
add_bytes_to_string(&pixels, (const char *)data, datalen);
|
||||
mem_free(data);
|
||||
|
@ -2230,6 +2230,19 @@ html_special(struct html_context *html_context, html_special_type_T c, ...)
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case SP_IMAGE:
|
||||
#ifdef CONFIG_LIBSIXEL
|
||||
{
|
||||
if (document) {
|
||||
struct uri *uri = va_arg(l, struct uri *);
|
||||
|
||||
add_to_uri_list(&document->image_uris, uri);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
|
||||
|
@ -34,7 +34,8 @@ enum html_special_type {
|
||||
SP_STYLESHEET,
|
||||
SP_COLOR_LINK_LINES,
|
||||
SP_SCRIPT,
|
||||
SP_IFRAME
|
||||
SP_IFRAME,
|
||||
SP_IMAGE
|
||||
};
|
||||
|
||||
typedef unsigned int html_special_type_T;
|
||||
|
@ -518,6 +518,24 @@ load_css_imports(struct session *ses, struct document_view *doc_view)
|
||||
#define load_css_imports(ses, doc_view)
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_LIBSIXEL
|
||||
static void
|
||||
load_images(struct session *ses, struct document_view *doc_view)
|
||||
{
|
||||
struct document *document = doc_view->document;
|
||||
struct uri *uri;
|
||||
int index;
|
||||
|
||||
if (!document) return;
|
||||
|
||||
foreach_uri (uri, index, &document->image_uris) {
|
||||
request_additional_file(ses, "", uri, PRI_CSS);
|
||||
}
|
||||
}
|
||||
#else
|
||||
#define load_images(ses, doc_view)
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_ECMASCRIPT
|
||||
static inline void
|
||||
load_ecmascript_imports(struct session *ses, struct document_view *doc_view)
|
||||
@ -557,6 +575,7 @@ load_frames(struct session *ses, struct document_view *doc_view)
|
||||
foreach (doc_view, ses->scrn_frames) {
|
||||
load_css_imports(ses, doc_view);
|
||||
load_ecmascript_imports(ses, doc_view);
|
||||
load_images(ses, ses->doc_view);
|
||||
}
|
||||
}
|
||||
|
||||
@ -589,6 +608,7 @@ load_common(struct session *ses)
|
||||
load_css_imports(ses, ses->doc_view);
|
||||
load_ecmascript_imports(ses, ses->doc_view);
|
||||
load_iframes(ses, ses->doc_view);
|
||||
load_images(ses, ses->doc_view);
|
||||
process_file_requests(ses);
|
||||
}
|
||||
|
||||
@ -759,6 +779,7 @@ doc_loading_callback(struct download *download, struct session *ses)
|
||||
load_frames(ses, ses->doc_view);
|
||||
load_css_imports(ses, ses->doc_view);
|
||||
load_ecmascript_imports(ses, ses->doc_view);
|
||||
load_images(ses, ses->doc_view);
|
||||
process_file_requests(ses);
|
||||
|
||||
start_document_refreshes(ses);
|
||||
|
@ -27,10 +27,18 @@
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#define _GNU_SOURCE /* See feature_test_macros(7) */
|
||||
#include <sys/mman.h>
|
||||
|
||||
int memfd_create(const char *name, unsigned int flags);
|
||||
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <sixel.h>
|
||||
#include <fcntl.h>
|
||||
#include <sys/stat.h>
|
||||
|
||||
#include "elinks.h"
|
||||
|
||||
@ -1033,3 +1041,66 @@ end:
|
||||
|
||||
return dest;
|
||||
}
|
||||
|
||||
unsigned char *
|
||||
el_sixel_get_image(char *data, int length)
|
||||
{
|
||||
SIXELSTATUS status = SIXEL_FALSE;
|
||||
sixel_encoder_t *encoder = NULL;
|
||||
unsigned char *ret = NULL;
|
||||
|
||||
status = sixel_encoder_new(&encoder, NULL);
|
||||
|
||||
if (SIXEL_FAILED(status)) {
|
||||
goto error;
|
||||
}
|
||||
int fdout = -1;
|
||||
|
||||
encoder->outfd = memfd_create("out.sixel", 0);
|
||||
fdout = dup(encoder->outfd);
|
||||
encoder->fstatic = 1;
|
||||
|
||||
int fdin = memfd_create("input.sixel", 0);
|
||||
FILE *f = fdopen(fdin, "wb");
|
||||
|
||||
if (!f) {
|
||||
goto error;
|
||||
}
|
||||
fwrite(data, 1, length, f);
|
||||
rewind(f);
|
||||
|
||||
struct string name;
|
||||
if (!init_string(&name)) {
|
||||
goto error;
|
||||
}
|
||||
add_format_to_string(&name, "/proc/self/fd/%d", fdin);
|
||||
status = sixel_encoder_encode(encoder, name.source);
|
||||
done_string(&name);
|
||||
|
||||
if (SIXEL_FAILED(status)) {
|
||||
goto error;
|
||||
}
|
||||
|
||||
struct stat sb;
|
||||
fstat(fdout, &sb);
|
||||
|
||||
if (sb.st_size > 0) {
|
||||
ret = (unsigned char *)mem_alloc(sb.st_size);
|
||||
|
||||
if (ret) {
|
||||
FILE *f2 = fdopen(fdout, "rb");
|
||||
if (f2) {
|
||||
rewind(f2);
|
||||
fread(ret, 1, (size_t)sb.st_size, f2);
|
||||
fclose(f2);
|
||||
}
|
||||
}
|
||||
}
|
||||
close(fdout);
|
||||
|
||||
error:
|
||||
fclose(f);
|
||||
end:
|
||||
sixel_encoder_unref(encoder);
|
||||
return ret;
|
||||
}
|
||||
|
@ -34,6 +34,7 @@ int add_image_to_document(struct document *doc, struct string *pixels, int linen
|
||||
|
||||
struct image *copy_frame(struct image *src, struct el_box *box, int cell_width, int cell_height, int dx, int dy);
|
||||
|
||||
unsigned char *el_sixel_get_image(char *data, int len);
|
||||
|
||||
#endif
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user