changeset 339:979960e65f76

js: add font bindings While here, correct int to long in font_render.
author David Demelier <markand@malikania.fr>
date Sat, 16 Oct 2021 09:01:20 +0200
parents 94828af916bb
children 64aff0afc8ac
files doc/docs/dev/api/core/font.md extern/libduktape/CMakeLists.txt src/libmlk-core-js/CMakeLists.txt src/libmlk-core-js/core/js-core.c src/libmlk-core-js/core/js-core.h src/libmlk-core-js/core/js-font.c src/libmlk-core-js/core/js-font.h src/libmlk-core/core/font.c src/libmlk-core/core/font.h src/libmlk-core/core/vfs.c src/libmlk-core/core/vfs.h src/libmlk-core/core/vfs_p.h src/mlk-run/main.c
diffstat 13 files changed, 434 insertions(+), 25 deletions(-) [+]
line wrap: on
line diff
--- a/doc/docs/dev/api/core/font.md	Thu Oct 14 21:21:28 2021 +0200
+++ b/doc/docs/dev/api/core/font.md	Sat Oct 16 09:01:20 2021 +0200
@@ -80,7 +80,7 @@
 
 ```c
 int
-font_render(struct font *font, struct texture *tex, const char *text, unsigned int color)
+font_render(struct font *font, struct texture *tex, const char *text, unsigned long color)
 ```
 
 ### font\_height
--- a/extern/libduktape/CMakeLists.txt	Thu Oct 14 21:21:28 2021 +0200
+++ b/extern/libduktape/CMakeLists.txt	Sat Oct 16 09:01:20 2021 +0200
@@ -22,7 +22,7 @@
 target_include_directories(
 	libmlk-duktape
 	PUBLIC
-		$<BUILD_INTERFACE:${libduktape_SOURCE_DIR}>
+		$<BUILD_INTERFACE:${libmlk-duktape_SOURCE_DIR}>
 )
 
 set_target_properties(libmlk-duktape PROPERTIES PREFIX "")
--- a/src/libmlk-core-js/CMakeLists.txt	Thu Oct 14 21:21:28 2021 +0200
+++ b/src/libmlk-core-js/CMakeLists.txt	Sat Oct 16 09:01:20 2021 +0200
@@ -22,8 +22,12 @@
 	SOURCES
 	${libmlk-core-js_SOURCE_DIR}/core/js-clock.c
 	${libmlk-core-js_SOURCE_DIR}/core/js-clock.h
+	${libmlk-core-js_SOURCE_DIR}/core/js-core.c
+	${libmlk-core-js_SOURCE_DIR}/core/js-core.h
 	${libmlk-core-js_SOURCE_DIR}/core/js-event.c
 	${libmlk-core-js_SOURCE_DIR}/core/js-event.h
+	${libmlk-core-js_SOURCE_DIR}/core/js-font.c
+	${libmlk-core-js_SOURCE_DIR}/core/js-font.h
 	${libmlk-core-js_SOURCE_DIR}/core/js-painter.c
 	${libmlk-core-js_SOURCE_DIR}/core/js-painter.h
 	${libmlk-core-js_SOURCE_DIR}/core/js-texture.c
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/libmlk-core-js/core/js-core.c	Sat Oct 16 09:01:20 2021 +0200
@@ -0,0 +1,51 @@
+/*
+ * js-core.c -- core binding
+ *
+ * Copyright (c) 2020-2021 David Demelier <markand@malikania.fr>
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <assert.h>
+
+#include "js-core.h"
+
+#define VFS DUK_HIDDEN_SYMBOL("Mlk.Vfs")
+
+void
+js_core_bind(duk_context *ctx, struct vfs *vfs)
+{
+	assert(ctx);
+	assert(vfs);
+
+	/* We put the VFS object. */
+	duk_push_global_stash(ctx);
+	duk_push_pointer(ctx, vfs);
+	duk_put_prop_string(ctx, -2, VFS);
+	duk_pop(ctx);
+}
+
+struct vfs *
+js_core_global_vfs(duk_context *ctx)
+{
+	assert(ctx);
+
+	struct vfs *vfs;
+
+	duk_push_global_stash(ctx);
+	duk_get_prop_string(ctx, -1, VFS);
+	vfs = duk_to_pointer(ctx, -1);
+	duk_pop(ctx);
+	
+	return vfs;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/libmlk-core-js/core/js-core.h	Sat Oct 16 09:01:20 2021 +0200
@@ -0,0 +1,32 @@
+/*
+ * js-core.h -- core binding
+ *
+ * Copyright (c) 2020-2021 David Demelier <markand@malikania.fr>
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef MLK_CORE_JS_H
+#define MLK_CORE_JS_H
+
+#include <duktape.h>
+
+struct vfs;
+
+void
+js_core_bind(duk_context *, struct vfs *);
+
+struct vfs *
+js_core_global_vfs(duk_context *);
+
+#endif /* !MLK_CORE_JS_H */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/libmlk-core-js/core/js-font.c	Sat Oct 16 09:01:20 2021 +0200
@@ -0,0 +1,176 @@
+/*
+ * js-font.c -- core texture binding
+ *
+ * Copyright (c) 2020-2021 David Demelier <markand@malikania.fr>
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <assert.h>
+
+#include <core/alloc.h>
+#include <core/error.h>
+#include <core/font.h>
+#include <core/texture.h>
+#include <core/vfs.h>
+
+#include "js-core.h"
+#include "js-font.h"
+#include "js-texture.h"
+
+#define SIGNATURE DUK_HIDDEN_SYMBOL("Mlk.Font")
+
+static inline struct font *
+self(duk_context *ctx)
+{
+	struct font *font;
+
+	duk_push_this(ctx);
+	duk_get_prop_string(ctx, -1, SIGNATURE);
+	font = duk_to_pointer(ctx, -1);
+	duk_pop_2(ctx);
+
+	if (!font)
+		duk_error(ctx, DUK_ERR_TYPE_ERROR, "not a Font object");
+
+	return font;
+}
+
+static duk_ret_t
+Font_getStyle(duk_context *ctx)
+{
+	duk_push_int(ctx, self(ctx)->style);
+
+	return 1;
+}
+
+static duk_ret_t
+Font_setStyle(duk_context *ctx)
+{
+	const int style = duk_require_int(ctx, 0);
+
+	if (style < 0 || style >= FONT_STYLE_LAST)
+		duk_error(ctx, DUK_ERR_ERROR, "invalid style");
+
+	self(ctx)->style = style;
+
+	return 0;
+}
+
+static duk_ret_t
+Font_getHeight(duk_context *ctx)
+{
+	duk_push_uint(ctx, font_height(self(ctx)));
+
+	return 1;
+}
+
+static duk_ret_t
+Font_new(duk_context *ctx)
+{
+	const char *entry = duk_require_string(ctx, 0);
+	const unsigned int size = duk_require_uint(ctx, 1);
+	struct vfs_file file;
+	struct font *font;
+
+	if (vfs_open(js_core_global_vfs(ctx), &file, entry, "r") < 0)
+		duk_error(ctx, DUK_ERR_ERROR, "%s", error());
+
+	font = alloc_new0(sizeof (*font));
+
+	if (font_openvfs(font, &file, size) < 0) {
+		free(font);
+		vfs_file_finish(&file);
+		duk_error(ctx, DUK_ERR_ERROR, "%s", error());
+	}
+
+	vfs_file_finish(&file);
+
+	duk_push_this(ctx);
+	duk_push_pointer(ctx, font);
+	duk_put_prop_string(ctx, -2, SIGNATURE);
+	duk_push_string(ctx, "style");
+	duk_push_c_function(ctx, Font_getStyle, 0);
+	duk_push_c_function(ctx, Font_setStyle, 1);
+	duk_def_prop(ctx, -4, DUK_DEFPROP_HAVE_GETTER | DUK_DEFPROP_HAVE_SETTER);
+	duk_push_string(ctx, "height");
+	duk_push_c_function(ctx, Font_getHeight, 0);
+	duk_def_prop(ctx, -3, DUK_DEFPROP_HAVE_GETTER);
+	duk_pop(ctx);
+
+	return 0;
+}
+
+static duk_ret_t
+Font_render(duk_context *ctx)
+{
+	const char *text = duk_require_string(ctx, 0);
+	unsigned long color = duk_require_uint(ctx, 1);
+	struct texture *tex;
+
+	tex = alloc_new0(sizeof (*tex));
+
+	if (font_render(self(ctx), tex, text, color) < 0) {
+		free(tex);
+		duk_error(ctx, DUK_ERR_ERROR, "%s", error());
+	}
+
+	js_texture_push(ctx, tex);
+
+	return 1;
+}
+
+static duk_ret_t
+Font_query(duk_context *ctx)
+{
+	const char *text = duk_require_string(ctx, 0);
+	unsigned int w, h;
+
+	if (font_query(self(ctx), text, &w, &h) < 0)
+		duk_error(ctx, DUK_ERR_ERROR, "%s", error());
+
+	duk_push_object(ctx);
+	duk_push_uint(ctx, w);
+	duk_put_prop_string(ctx, -2, "w");
+	duk_push_uint(ctx, h);
+	duk_put_prop_string(ctx, -2, "h");
+
+	return 1;
+}
+
+static const struct duk_function_list_entry methods[] = {
+	{ "render",     Font_render,    2 },
+	{ "query",      Font_query,     1 },
+	{ NULL,         NULL,           0 }
+};
+
+static const struct duk_number_list_entry styles[] = {
+	{ "ANTIALIASED",        FONT_STYLE_ANTIALIASED, },
+	{ "NONE",               FONT_STYLE_NONE         },
+	{ NULL,                 0                       }
+};
+
+void
+js_font_bind(duk_context *ctx)
+{
+	assert(ctx);
+
+	duk_push_c_function(ctx, Font_new, 2);
+	duk_push_object(ctx);
+	duk_put_number_list(ctx, -1, styles);
+	duk_put_prop_string(ctx, -2, "Style");
+	duk_push_object(ctx);
+	duk_put_function_list(ctx, -1, methods);
+	duk_put_prop_string(ctx, -2, "prototype");
+	duk_put_global_string(ctx, "Font");
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/libmlk-core-js/core/js-font.h	Sat Oct 16 09:01:20 2021 +0200
@@ -0,0 +1,27 @@
+/*
+ * js-font.h -- core texture binding
+ *
+ * Copyright (c) 2020-2021 David Demelier <markand@malikania.fr>
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef MLK_CORE_JS_FONT_H
+#define MLK_CORE_JS_FONT_H
+
+#include <duktape.h>
+
+void
+js_font_bind(duk_context *);
+
+#endif /* !MLK_CORE_JS_FONT_H */
--- a/src/libmlk-core/core/font.c	Thu Oct 14 21:21:28 2021 +0200
+++ b/src/libmlk-core/core/font.c	Sat Oct 16 09:01:20 2021 +0200
@@ -26,6 +26,8 @@
 #include "font.h"
 #include "texture_p.h"
 #include "util.h"
+#include "vfs.h"
+#include "vfs_p.h"
 
 int
 font_open(struct font *font, const char *path, unsigned int size)
@@ -55,13 +57,29 @@
 }
 
 int
+font_openvfs(struct font *font, struct vfs_file *file, unsigned int size)
+{
+	assert(font);
+	assert(vfs_file_ok(file));
+
+	SDL_RWops *ops;
+
+	if (!(ops = vfs_to_rw(file)))
+		return -1;
+	if (!(font->handle = TTF_OpenFontRW(ops, 1, size)))
+		return errorf("%s", SDL_GetError());
+
+	return 0;
+}
+
+int
 font_ok(const struct font *font)
 {
 	return font && font->handle;
 }
 
 int
-font_render(struct font *font, struct texture *tex, const char *text, unsigned int color)
+font_render(struct font *font, struct texture *tex, const char *text, unsigned long color)
 {
 	assert(font_ok(font));
 	assert(text);
--- a/src/libmlk-core/core/font.h	Thu Oct 14 21:21:28 2021 +0200
+++ b/src/libmlk-core/core/font.h	Sat Oct 16 09:01:20 2021 +0200
@@ -24,10 +24,12 @@
 #include "core.h"
 
 struct texture;
+struct vfs_file;
 
 enum font_style {
 	FONT_STYLE_ANTIALIASED,
-	FONT_STYLE_NONE
+	FONT_STYLE_NONE,
+	FONT_STYLE_LAST
 };
 
 struct font {
@@ -44,10 +46,13 @@
 font_openmem(struct font *, const void *, size_t, unsigned int);
 
 int
+font_openvfs(struct font *, struct vfs_file *, unsigned int);
+
+int
 font_ok(const struct font *);
 
 int
-font_render(struct font *, struct texture *, const char *, unsigned int);
+font_render(struct font *, struct texture *, const char *, unsigned long);
 
 unsigned int
 font_height(const struct font *);
--- a/src/libmlk-core/core/vfs.c	Thu Oct 14 21:21:28 2021 +0200
+++ b/src/libmlk-core/core/vfs.c	Sat Oct 16 09:01:20 2021 +0200
@@ -17,9 +17,14 @@
  */
 
 #include <assert.h>
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
 #include <string.h>
 
+#include "error.h"
 #include "vfs.h"
+#include "vfs_p.h"
 
 int
 vfs_open(struct vfs *vfs, struct vfs_file *file, const char *entry, const char *mode)
@@ -32,6 +37,12 @@
 	return vfs->open(vfs, file, entry, mode);
 }
 
+int
+vfs_ok(struct vfs *vfs)
+{
+	return vfs && vfs->open && vfs->finish;
+}
+
 void
 vfs_finish(struct vfs *vfs)
 {
@@ -41,6 +52,12 @@
 	memset(vfs, 0, sizeof (*vfs));
 }
 
+int
+vfs_file_ok(struct vfs_file *file)
+{
+	return file && file->read && file->write && file->flush && file->finish;
+}
+
 size_t
 vfs_file_read(struct vfs_file *file, void *buf, size_t bufsz)
 {
@@ -50,6 +67,33 @@
 	return file->read(file, buf, bufsz);
 }
 
+char *
+vfs_file_aread(struct vfs_file *file, size_t *outlen)
+{
+	FILE *fp;
+	char *out = NULL, buf[BUFSIZ];
+	size_t len, nr;
+
+	if (!(fp = open_memstream(&out, &len)))
+		return errorf("%s", strerror(errno)), NULL;
+
+	while ((nr = vfs_file_read(file, buf, sizeof (buf))) > 0) {
+		if (fwrite(buf, 1, nr, fp) != nr) {
+			errorf("%s", strerror(errno));
+			fclose(fp);
+			free(out);
+			return NULL;
+		}
+	}
+
+	fclose(fp);
+
+	if (outlen)
+		*outlen = len;
+
+	return out;
+}
+
 size_t
 vfs_file_write(struct vfs_file *file, void *buf, size_t bufsz)
 {
@@ -74,3 +118,33 @@
 
 	file->finish(file);
 }
+
+/* private */
+
+static int
+rw_vfs_file_close(SDL_RWops *context)
+{
+	free(context->hidden.mem.base);
+	free(context);
+
+	return 0;
+}
+
+SDL_RWops *
+vfs_to_rw(struct vfs_file *file)
+{
+	SDL_RWops *ops;
+	char *data;
+	size_t datasz;
+
+	if (!(data = vfs_file_aread(file, &datasz)))
+		return NULL;
+	if (!(ops = SDL_RWFromConstMem(data, datasz))) {
+		free(data);
+		return errorf("%s", SDL_GetError()), NULL;
+	}
+
+	ops->close = rw_vfs_file_close;
+
+	return ops;
+}
--- a/src/libmlk-core/core/vfs.h	Thu Oct 14 21:21:28 2021 +0200
+++ b/src/libmlk-core/core/vfs.h	Sat Oct 16 09:01:20 2021 +0200
@@ -44,14 +44,23 @@
 int
 vfs_open(struct vfs *, struct vfs_file *, const char *, const char *);
 
+int
+vfs_ok(struct vfs *);
+
 void
 vfs_finish(struct vfs *);
 
 /* vfs_file */
 
+int
+vfs_file_ok(struct vfs_file *);
+
 size_t
 vfs_file_read(struct vfs_file *, void *, size_t);
 
+char *
+vfs_file_aread(struct vfs_file *, size_t *);
+
 size_t
 vfs_file_write(struct vfs_file *, void *, size_t);
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/libmlk-core/core/vfs_p.h	Sat Oct 16 09:01:20 2021 +0200
@@ -0,0 +1,27 @@
+/*
+ * vfs.h -- (PRIVATE) virtual file system abstraction
+ *
+ * Copyright (c) 2020-2021 David Demelier <markand@malikania.fr>
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef MOLKO_CORE_VFS_P_H
+#define MOLKO_CORE_VFS_P_H
+
+#include <SDL.h>
+
+SDL_RWops *
+vfs_to_rw(struct vfs_file *);
+
+#endif /* !MOLKO_CORE_VFS_P_H */
--- a/src/mlk-run/main.c	Thu Oct 14 21:21:28 2021 +0200
+++ b/src/mlk-run/main.c	Sat Oct 16 09:01:20 2021 +0200
@@ -27,7 +27,9 @@
 #include <core/vfs.h>
 
 #include <core/js-clock.h>
+#include <core/js-core.h>
 #include <core/js-event.h>
+#include <core/js-font.h>
 #include <core/js-painter.h>
 #include <core/js-texture.h>
 #include <core/js-window.h>
@@ -50,6 +52,8 @@
 core_bind(duk_context *ctx)
 {
 	js_clock_bind(ctx);
+	js_core_bind(ctx, &vfs);
+	js_font_bind(ctx);
 	js_event_bind(ctx);
 	js_painter_bind(ctx);
 	js_texture_bind(ctx);
@@ -74,25 +78,6 @@
 	duk_pop(ctx);
 }
 
-static char *
-extract(struct vfs_file *file)
-{
-	FILE *fp;
-	char *out, buf[BUFSIZ];
-	size_t len, nr;
-
-	if (!(fp = open_memstream(&out, &len)))
-		panic();
-
-	while ((nr = vfs_file_read(file, buf, sizeof (buf))) > 0)
-		if (fwrite(buf, 1, nr, fp) <= 0)
-			panic();
-
-	fclose(fp);
-
-	return out;
-}
-
 static void
 startup(void)
 {
@@ -101,8 +86,9 @@
 
 	if (vfs_open(&vfs, &main, "main.js", "r") < 0)
 		panic();
+	if (!(code = vfs_file_aread(&main, NULL)))
+		panic();
 
-	code = extract(&main);
 	vfs_file_finish(&main);
 
 	if (duk_peval_string(ctx, code))