129 lines
4.1 KiB
C
129 lines
4.1 KiB
C
#include "qjs_staef.h"
|
|
#include "font.h"
|
|
#include "qjs_macros.h"
|
|
#include "HandmadeMath.h"
|
|
#include "render.h"
|
|
#include "stb_ds.h"
|
|
#include "cell.h"
|
|
#include "qjs_sdl.h"
|
|
#include <SDL3/SDL.h>
|
|
|
|
// External functions from jsffi.c
|
|
typedef HMM_Vec4 colorf;
|
|
extern colorf js2color(JSContext *js, JSValue v);
|
|
extern JSValue vec22js(JSContext *js, HMM_Vec2 v);
|
|
extern HMM_Vec2 js2vec2(JSContext *js, JSValue v);
|
|
extern rect js2rect(JSContext *js, JSValue v);
|
|
extern double js2number(JSContext *js, JSValue v);
|
|
extern JSValue number2js(JSContext *js, double g);
|
|
extern void *js_get_blob_data(JSContext *js, size_t *len, JSValue v);
|
|
extern JSValue js_new_blob_stoned_copy(JSContext *js, void *data, size_t size);
|
|
extern JSValue quads_to_mesh(JSContext *js, text_vert *buffer);
|
|
extern int uncaught_exception(JSContext *js, JSValue ret);
|
|
|
|
// QuickJS class for font
|
|
QJSCLASS(font,)
|
|
|
|
// Font constructor
|
|
JSC_CCALL(staef_font_new,
|
|
size_t len;
|
|
void *data = js_get_blob_data(js, &len, argv[0]);
|
|
if (!data) return JS_ThrowReferenceError(js, "could not get array buffer data");
|
|
|
|
double height = js2number(js, argv[1]);
|
|
font *f = MakeFont(data, len, (int)height);
|
|
if (!f) return JS_ThrowReferenceError(js, "could not create font");
|
|
|
|
ret = font2js(js, f);
|
|
|
|
// Create surface data object for the font's atlas
|
|
if (f->surface) {
|
|
JSValue surfData = JS_NewObject(js);
|
|
JS_SetPropertyStr(js, surfData, "width", JS_NewInt32(js, f->surface->w));
|
|
JS_SetPropertyStr(js, surfData, "height", JS_NewInt32(js, f->surface->h));
|
|
JS_SetPropertyStr(js, surfData, "format", pixelformat2js(js, f->surface->format));
|
|
JS_SetPropertyStr(js, surfData, "pitch", JS_NewInt32(js, f->surface->pitch));
|
|
|
|
// Lock surface if needed
|
|
int locked = 0;
|
|
if (SDL_MUSTLOCK(f->surface)) {
|
|
if (SDL_LockSurface(f->surface) < 0)
|
|
return JS_ThrowInternalError(js, "Lock surface failed: %s", SDL_GetError());
|
|
locked = 1;
|
|
}
|
|
|
|
size_t byte_size = f->surface->pitch * f->surface->h;
|
|
JS_SetPropertyStr(js, surfData, "pixels", js_new_blob_stoned_copy(js, f->surface->pixels, byte_size));
|
|
|
|
if (locked)
|
|
SDL_UnlockSurface(f->surface);
|
|
|
|
JS_SetPropertyStr(js, ret, "surface", surfData);
|
|
}
|
|
)
|
|
|
|
// Calculate text size
|
|
JSC_CCALL(staef_font_text_size,
|
|
font *f = js2font(js, self);
|
|
const char *str = JS_ToCString(js, argv[0]);
|
|
float letterSpacing = argc > 1 ? js2number(js, argv[1]) : 0;
|
|
float wrap = argc > 2 ? js2number(js, argv[2]) : -1;
|
|
|
|
ret = vec22js(js, measure_text(str, f, letterSpacing, wrap));
|
|
JS_FreeCString(js, str);
|
|
)
|
|
|
|
// Generate text buffer (mesh data)
|
|
JSC_CCALL(staef_font_make_text_buffer,
|
|
font *f = js2font(js, self);
|
|
const char *s = JS_ToCString(js, argv[0]);
|
|
rect rectpos = js2rect(js, argv[1]);
|
|
colorf c = js2color(js, argv[2]);
|
|
float wrap = argc > 3 ? js2number(js, argv[3]) : -1;
|
|
|
|
HMM_Vec2 startpos = {.x = rectpos.x, .y = rectpos.y };
|
|
text_vert *buffer = renderText(s, startpos, f, c, wrap);
|
|
ret = quads_to_mesh(js, buffer);
|
|
JS_FreeCString(js, s);
|
|
arrfree(buffer);
|
|
)
|
|
|
|
// Font property getters/setters
|
|
JSC_GETSET(font, linegap, number)
|
|
|
|
// Font methods
|
|
static const JSCFunctionListEntry js_font_funcs[] = {
|
|
MIST_FUNC_DEF(staef_font, text_size, 3),
|
|
MIST_FUNC_DEF(staef_font, make_text_buffer, 4),
|
|
CGETSET_ADD(font, linegap),
|
|
};
|
|
|
|
// Font constructor function
|
|
static JSValue js_font_constructor(JSContext *ctx, JSValueConst new_target, int argc, JSValueConst *argv)
|
|
{
|
|
return js_staef_font_new(ctx, JS_NULL, argc, argv);
|
|
}
|
|
|
|
// Initialize the staef module
|
|
JSValue js_staef_use(JSContext *js)
|
|
{
|
|
JSValue mod = JS_NewObject(js);
|
|
JSValue proto;
|
|
|
|
// Initialize font class
|
|
JS_NewClassID(&js_font_id);
|
|
JS_NewClass(JS_GetRuntime(js), js_font_id, &js_font_class);
|
|
proto = JS_NewObject(js);
|
|
JS_SetPropertyFunctionList(js, proto, js_font_funcs, countof(js_font_funcs));
|
|
JS_SetClassProto(js, js_font_id, proto);
|
|
|
|
// Create font constructor
|
|
JSValue font_ctor = JS_NewCFunction2(js, js_font_constructor, "font", 2, JS_CFUNC_constructor, 0);
|
|
JS_SetConstructor(js, font_ctor, proto);
|
|
|
|
// Add font constructor to module (lowercase to match "new staef.font")
|
|
JS_SetPropertyStr(js, mod, "font", font_ctor);
|
|
|
|
return mod;
|
|
}
|