mirror of
https://github.com/rkd77/elinks.git
synced 2025-06-30 22:19:29 -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)) {
|
while (!list_empty(document->images)) {
|
||||||
delete_image((struct image *)document->images.next);
|
delete_image((struct image *)document->images.next);
|
||||||
}
|
}
|
||||||
|
free_uri_list(&document->image_uris);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef CONFIG_CSS
|
#ifdef CONFIG_CSS
|
||||||
|
@ -313,6 +313,7 @@ struct document {
|
|||||||
enum clipboard_status clipboard_status;
|
enum clipboard_status clipboard_status;
|
||||||
#ifdef CONFIG_LIBSIXEL
|
#ifdef CONFIG_LIBSIXEL
|
||||||
LIST_OF(struct image) images;
|
LIST_OF(struct image) images;
|
||||||
|
struct uri_list image_uris;
|
||||||
#endif
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -26,6 +26,7 @@
|
|||||||
#include "bfu/listmenu.h"
|
#include "bfu/listmenu.h"
|
||||||
#include "bfu/menu.h"
|
#include "bfu/menu.h"
|
||||||
#include "bookmarks/bookmarks.h"
|
#include "bookmarks/bookmarks.h"
|
||||||
|
#include "cache/cache.h"
|
||||||
#include "config/options.h"
|
#include "config/options.h"
|
||||||
#include "config/kbdbind.h"
|
#include "config/kbdbind.h"
|
||||||
#include "document/html/frames.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) {
|
if (!html_context->options->sixel || !html_context->document) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
unsigned char *data = NULL;
|
||||||
|
int datalen = 0;
|
||||||
char *elsix = get_attr_val(a, "elsix", html_context->doc_cp);
|
char *elsix = get_attr_val(a, "elsix", html_context->doc_cp);
|
||||||
|
|
||||||
if (!elsix) {
|
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;
|
struct string pixels;
|
||||||
|
|
||||||
if (!init_string(&pixels)) {
|
if (!init_string(&pixels)) {
|
||||||
mem_free(elsix);
|
mem_free_if(elsix);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
int datalen;
|
if (!datalen) {
|
||||||
unsigned char *data = base64_decode_bin((const unsigned char *)elsix, strlen(elsix), &datalen);
|
data = base64_decode_bin((const unsigned char *)elsix, strlen(elsix), &datalen);
|
||||||
|
|
||||||
mem_free(elsix);
|
mem_free(elsix);
|
||||||
|
|
||||||
if (!data) {
|
if (!data) {
|
||||||
done_string(&pixels);
|
done_string(&pixels);
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
add_bytes_to_string(&pixels, (const char *)data, datalen);
|
add_bytes_to_string(&pixels, (const char *)data, datalen);
|
||||||
mem_free(data);
|
mem_free(data);
|
||||||
|
@ -2230,6 +2230,19 @@ html_special(struct html_context *html_context, html_special_type_T c, ...)
|
|||||||
}
|
}
|
||||||
break;
|
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:
|
default:
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
@ -34,7 +34,8 @@ enum html_special_type {
|
|||||||
SP_STYLESHEET,
|
SP_STYLESHEET,
|
||||||
SP_COLOR_LINK_LINES,
|
SP_COLOR_LINK_LINES,
|
||||||
SP_SCRIPT,
|
SP_SCRIPT,
|
||||||
SP_IFRAME
|
SP_IFRAME,
|
||||||
|
SP_IMAGE
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef unsigned int html_special_type_T;
|
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)
|
#define load_css_imports(ses, doc_view)
|
||||||
#endif
|
#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
|
#ifdef CONFIG_ECMASCRIPT
|
||||||
static inline void
|
static inline void
|
||||||
load_ecmascript_imports(struct session *ses, struct document_view *doc_view)
|
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) {
|
foreach (doc_view, ses->scrn_frames) {
|
||||||
load_css_imports(ses, doc_view);
|
load_css_imports(ses, doc_view);
|
||||||
load_ecmascript_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_css_imports(ses, ses->doc_view);
|
||||||
load_ecmascript_imports(ses, ses->doc_view);
|
load_ecmascript_imports(ses, ses->doc_view);
|
||||||
load_iframes(ses, ses->doc_view);
|
load_iframes(ses, ses->doc_view);
|
||||||
|
load_images(ses, ses->doc_view);
|
||||||
process_file_requests(ses);
|
process_file_requests(ses);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -759,6 +779,7 @@ doc_loading_callback(struct download *download, struct session *ses)
|
|||||||
load_frames(ses, ses->doc_view);
|
load_frames(ses, ses->doc_view);
|
||||||
load_css_imports(ses, ses->doc_view);
|
load_css_imports(ses, ses->doc_view);
|
||||||
load_ecmascript_imports(ses, ses->doc_view);
|
load_ecmascript_imports(ses, ses->doc_view);
|
||||||
|
load_images(ses, ses->doc_view);
|
||||||
process_file_requests(ses);
|
process_file_requests(ses);
|
||||||
|
|
||||||
start_document_refreshes(ses);
|
start_document_refreshes(ses);
|
||||||
|
@ -27,10 +27,18 @@
|
|||||||
#include "config.h"
|
#include "config.h"
|
||||||
#endif
|
#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 <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <sixel.h>
|
#include <sixel.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
|
||||||
#include "elinks.h"
|
#include "elinks.h"
|
||||||
|
|
||||||
@ -1033,3 +1041,66 @@ end:
|
|||||||
|
|
||||||
return dest;
|
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);
|
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
|
#endif
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user