diff --git a/emcc.c b/emcc.c index 1d88bfd..1a84efb 100644 --- a/emcc.c +++ b/emcc.c @@ -72,10 +72,10 @@ extern void js_canvas_draw_poly(const int *points, int npoints, extern void js_canvas_draw_circle(int x, int y, int r, const char *fillcolour, const char *outlinecolour); -extern int js_canvas_find_font_midpoint(int height, const char *fontptr); +extern int js_canvas_find_font_midpoint(int height, bool monospaced); extern void js_canvas_draw_text(int x, int y, int halign, - const char *colptr, const char *fontptr, - const char *text); + const char *colptr, int height, + bool monospaced, const char *text); extern int js_canvas_new_blitter(int w, int h); extern void js_canvas_free_blitter(int id); extern void js_canvas_copy_to_blitter(int id, int x, int y, int w, int h); @@ -444,14 +444,10 @@ static void js_draw_text(void *handle, int x, int y, int fonttype, int fontsize, int align, int colour, const char *text) { - char fontstyle[80]; int halign; - sprintf(fontstyle, "%dpx %s", fontsize, - fonttype == FONT_FIXED ? "monospace" : "sans-serif"); - if (align & ALIGN_VCENTRE) - y += js_canvas_find_font_midpoint(fontsize, fontstyle); + y += js_canvas_find_font_midpoint(fontsize, fonttype == FONT_FIXED); if (align & ALIGN_HCENTRE) halign = 1; @@ -460,7 +456,8 @@ static void js_draw_text(void *handle, int x, int y, int fonttype, else halign = 0; - js_canvas_draw_text(x, y, halign, colour_strings[colour], fontstyle, text); + js_canvas_draw_text(x, y, halign, colour_strings[colour], + fontsize, fonttype == FONT_FIXED, text); } static void js_draw_rect(void *handle, int x, int y, int w, int h, int colour) diff --git a/emcclib.js b/emcclib.js index 814ff56..02085bd 100644 --- a/emcclib.js +++ b/emcclib.js @@ -386,7 +386,7 @@ mergeInto(LibraryManager.library, { }, /* - * int js_canvas_find_font_midpoint(int height, const char *fontptr); + * int js_canvas_find_font_midpoint(int height, bool monospaced); * * Return the adjustment required for text displayed using * ALIGN_VCENTRE. We want to place the midpoint between the @@ -405,16 +405,17 @@ mergeInto(LibraryManager.library, { * Since this is a very expensive operation, we cache the results * per (font,height) pair. */ - js_canvas_find_font_midpoint: function(height, font) { - font = UTF8ToString(font); + js_canvas_find_font_midpoint: function(height, monospaced) { + + // Resolve the font into a string. + var ctx1 = onscreen_canvas.getContext('2d', { alpha: false }); + canvas_set_font(ctx1, height, monospaced); // Reuse cached value if possible - if (midpoint_cache[font] !== undefined) - return midpoint_cache[font]; + if (midpoint_cache[ctx1.font] !== undefined) + return midpoint_cache[ctx1.font]; // Find the width of the string - var ctx1 = onscreen_canvas.getContext('2d', { alpha: false }); - ctx1.font = font; var width = (ctx1.measureText(midpoint_test_str).width + 1) | 0; // Construct a test canvas of appropriate size, initialise it to @@ -427,7 +428,7 @@ mergeInto(LibraryManager.library, { ctx2.fillRect(0, 0, width, 2*height); var baseline = (1.5*height) | 0; ctx2.fillStyle = "#ffffff"; - ctx2.font = font; + canvas_set_font(ctx2, height, monospaced); ctx2.fillText(midpoint_test_str, 0, baseline); // Scan the contents of the test canvas to find the top and bottom @@ -445,22 +446,23 @@ mergeInto(LibraryManager.library, { } var ret = (baseline - (ymin + ymax) / 2) | 0; - midpoint_cache[font] = ret; + midpoint_cache[ctx1.font] = ret; return ret; }, /* * void js_canvas_draw_text(int x, int y, int halign, - * const char *colptr, const char *fontptr, - * const char *text); + * const char *colptr, int height, + * bool monospaced, const char *text); * * Draw text. Vertical alignment has been taken care of on the C * side, by optionally calling the above function. Horizontal * alignment is handled here, since we can get the canvas draw * function to do it for us with almost no extra effort. */ - js_canvas_draw_text: function(x, y, halign, colptr, fontptr, text) { - ctx.font = UTF8ToString(fontptr); + js_canvas_draw_text: function(x, y, halign, colptr, fontsize, monospaced, + text) { + canvas_set_font(ctx, fontsize, monospaced); ctx.fillStyle = UTF8ToString(colptr); ctx.textAlign = (halign == 0 ? 'left' : halign == 1 ? 'center' : 'right'); diff --git a/emccpre.js b/emccpre.js index 4cd5787..f7e0cc5 100644 --- a/emccpre.js +++ b/emccpre.js @@ -179,6 +179,22 @@ function canvas_mouse_coords(event, element) { return {x: rcoords.x * xscale, y: rcoords.y * yscale} } +// Set the font on a CanvasRenderingContext2d based on the CSS font +// for the canvas, the requested size, and whether we want something +// monospaced. +function canvas_set_font(ctx, size, monospaced) { + var s = window.getComputedStyle(onscreen_canvas); + // First set something that we're certain will work. Constructing + // the font string from the computed style is a bit fragile, so + // this acts as a fallback. + ctx.font = `${size}px ` + (monospaced ? "monospace" : "sans-serif"); + // In CSS Fonts Module Level 4, "font-stretch" gets serialised as + // a percentage, which can't be used in + // CanvasRenderingContext2d.font, so we omit it. + ctx.font = `${s.fontStyle} ${s.fontWeight} ${size}px ` + + (monospaced ? "monospace" : s.fontFamily); +} + // Enable and disable items in the CSS menus. function disable_menu_item(item, disabledFlag) { item.disabled = disabledFlag; diff --git a/html/jspage.pl b/html/jspage.pl index 0174fe1..de70b30 100755 --- a/html/jspage.pl +++ b/html/jspage.pl @@ -305,6 +305,7 @@ main { #puzzlecanvas { display: block; width: 100%; + /* This sets the font that will be used in the puzzle. */ font-family: sans-serif; }