From 20ce465eb5a25dbc318ef6872bc3c8137954c463 Mon Sep 17 00:00:00 2001 From: UnknownShadow200 Date: Fri, 3 Dec 2021 21:44:21 +1100 Subject: [PATCH] WIP on implementing system fonts in webclient Although either memory or canvas gets corrupted.. still trying to work out what's going on there --- src/Drawer2D.c | 29 ++++++++++++++++++--- src/Menus.c | 5 ---- src/interop_web.js | 64 ++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 89 insertions(+), 9 deletions(-) diff --git a/src/Drawer2D.c b/src/Drawer2D.c index ae5e448db..8b4d385fc 100644 --- a/src/Drawer2D.c +++ b/src/Drawer2D.c @@ -684,18 +684,39 @@ cc_string Font_Lookup(const cc_string* fontName, int flags) { return String_Empt cc_result Font_Make(struct FontDesc* desc, const cc_string* fontName, int size, int flags) { desc->size = size; desc->flags = flags; - desc->height = 0; + desc->height = size; + + desc->handle = Mem_TryAlloc(fontName->length + 1, 1); + if (!desc->handle) return 0; + + String_CopyToRaw(desc->handle, fontName->length + 1, fontName); return 0; } -void Font_MakeDefault(struct FontDesc* desc, int size, int flags) { Font_Make(desc, NULL, size, flags); } +void Font_MakeDefault(struct FontDesc* desc, int size, int flags) { + font_candidates[0].length = 0; + String_AppendConst(&font_candidates[0], "serif"); + Font_Make(desc, &font_candidates[0], size, flags); +} void Font_Free(struct FontDesc* desc) { + Mem_Free(desc->handle); + desc->handle = NULL; desc->size = 0; } void SysFonts_Register(const cc_string* path) { } -static int Font_SysTextWidth(struct DrawTextArgs* args) { return 0; } -static void Font_SysTextDraw(struct DrawTextArgs* args, struct Bitmap* bmp, int x, int y, cc_bool shadow) { } +extern int interop_TextWidth(const char* font, int size, const char* text, const int len); +extern void interop_TextDraw(const char* font, int size, const char* text, const int len, + struct Bitmap* bmp, int x, int y); + +static int Font_SysTextWidth(struct DrawTextArgs* args) { + struct FontDesc* font = args->font; + return interop_TextWidth(font->handle, font->size, args->text.buffer, args->text.length); +} +static void Font_SysTextDraw(struct DrawTextArgs* args, struct Bitmap* bmp, int x, int y, cc_bool shadow) { + struct FontDesc* font = args->font; + interop_TextDraw(font->handle, font->size, args->text.buffer, args->text.length, bmp, x, y); +} #else #include "freetype/ft2build.h" #include "freetype/freetype.h" diff --git a/src/Menus.c b/src/Menus.c index 1b6cec38c..86775ddca 100644 --- a/src/Menus.c +++ b/src/Menus.c @@ -2934,11 +2934,6 @@ static void GuiOptionsScreen_InitWidgets(struct MenuOptionsScreen* s) { s->numCore = 7; s->maxVertices += 7 * BUTTONWIDGET_MAX; MenuOptionsScreen_InitButtons(s, buttons, Array_Elems(buttons), Menu_SwitchOptions); -#ifdef CC_BUILD_WEB - /* TODO: Support system fonts in webclient */ - s->buttons[5].disabled = true; - s->buttons[6].disabled = true; -#endif } void GuiOptionsScreen_Show(void) { diff --git a/src/interop_web.js b/src/interop_web.js index 877e6f133..fc7bc19e1 100644 --- a/src/interop_web.js +++ b/src/interop_web.js @@ -815,4 +815,68 @@ mergeInto(LibraryManager.library, { var str = AUDIO.errors[errCode - 1]; return stringToUTF8(str, buffer, bufferLen); }, + + +//######################################################################################################################## +//-----------------------------------------------------------Font--------------------------------------------------------- +//######################################################################################################################## + interop_TextInit: function(font, size) { + if (!window.FONT_CANVAS) { + window.FONT_CANVAS = document.createElement('canvas'); + window.FONT_CONTEXT = window.FONT_CANVAS.getContext('2d'); + } + + var ctx = window.FONT_CONTEXT; + ctx.font = size + 'px ' + font; + ctx.textAlign = 'left'; + ctx.textBaseline = 'top'; + return ctx; + }, + interop_TextWidth__deps: ['interop_TextInit'], + interop_TextWidth: function(fontStr, fontSize, textStr, textLen) { + var font = UTF8ToString(fontStr); + var text = UTF8ArrayToString(HEAPU8, textStr, textLen); + + var ctx = _interop_TextInit(font, fontSize); + var data = ctx.measureText(text); + return Math.ceil(data.width)|0; + }, + interop_TextDraw__deps: ['interop_TextInit'], + interop_TextDraw: function(fontStr, fontSize, textStr, textLen, bmp, dstX, dstY) { + var font = UTF8ToString(fontStr); + var text = UTF8ArrayToString(HEAPU8, textStr, textLen); + + var ctx = _interop_TextInit(font, fontSize); + ctx.fillStyle = "#ffffff"; + ctx.fillRect(0, 0, ctx.canvas.width, ctx.canvas.height); + ctx.fillStyle = "#000000"; + ctx.fillText(text, 0, 0); + + var dst_pixels = HEAP32[(bmp|0 + 0)>>2]; + var dst_width = HEAP32[(bmp|0 + 4)>>2]; + var dst_height = HEAP32[(bmp|0 + 8)>>2]; + + // TODO not all of it + var src = ctx.getImageData(0, 0, ctx.canvas.width, ctx.canvas.height); + var src_pixels = src.data; + var src_width = src.width|0; + var src_height = src.height|0; + + var img_width = Math.min(src_width, dst_width); + var img_height = Math.min(src_height, dst_height); + + for (var y = 0; y < img_height; y++) + { + var src_row = (y*(src_width << 2))|0; + var dst_row = dst_pixels + (y*(dst_width << 2))|0; + + for (var x = 0; x < img_width; x++) + { + HEAPU8[dst_row + (x<<2)+0] = src_pixels[src_row + (x<<2)+0]; + HEAPU8[dst_row + (x<<2)+1] = src_pixels[src_row + (x<<2)+1]; + HEAPU8[dst_row + (x<<2)+2] = src_pixels[src_row + (x<<2)+2]; + HEAPU8[dst_row + (x<<2)+3] = 255; + } + } + }, }); \ No newline at end of file