Skip to content

Commit

Permalink
Add generic font interface + sample (#192)
Browse files Browse the repository at this point in the history
Signed-off-by: Marek Maškarinec <marek@mrms.cz>
  • Loading branch information
marekmaskarinec committed Jul 14, 2024
1 parent c7813a9 commit 34ab8b9
Show file tree
Hide file tree
Showing 8 changed files with 200 additions and 89 deletions.
2 changes: 1 addition & 1 deletion lib/sokol
33 changes: 33 additions & 0 deletions samples/font/combined/main.um
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@

import (
"canvas.um"
"font.um"
"input.um"
"std.um"
"th.um"
"window.um"
)

var fonts: [2]font::Font
var idx: int

fn init*() {
window::setup("combined font sample", 640, 480)

var err: std::Err
fonts[0], err = font::load("../../../etc/roboto.ttf", 16, .nearest)
std::exitif(err)

fonts[1] = canvas::pixelFont

window::onFrame.register({
const scale = 2.0
m := fonts[idx].measure("Press SPACE").mulf(scale)
pos := window::wp.sub(m).divf(2)
fonts[idx].draw("Press SPACE", pos, th::black, scale)

if input::isJustPressed(.space) {
idx = (idx + 1) % len(fonts)
}
})
}
25 changes: 25 additions & 0 deletions samples/font/ttf/main.um
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@

import (
"canvas.um"
"th.um"
"window.um"
"std.um"
"font.um"
)

var f: font::Font

fn init*() {
window::setup("font sample", 640, 480)

var err: std::Err
f, err = font::load("../../../etc/roboto.ttf", 16, .nearest)
std::exitif(err)

window::onFrame.register({
const scale = 2.0
m := f.measure("Hello World!").mulf(scale)
pos := window::wp.sub(m).divf(2)
f.draw("Hello World!", pos, th::black, scale)
})
}
18 changes: 9 additions & 9 deletions src/bindings.c
Original file line number Diff line number Diff line change
Expand Up @@ -120,9 +120,9 @@ umth_placeholder_fetch(UmkaStackSlot *p, UmkaStackSlot *r)
///////////////////////////
// FONT

// fn umth_font_load(out: ^Font, path: str, size: real, filter: uint32): th::ErrCode
// fn umth_ttf_font_load(out: ^TtfFont, path: str, size: real, filter: uint32): th::ErrCode
static void
umth_font_load(UmkaStackSlot *p, UmkaStackSlot *r)
umth_ttf_font_load(UmkaStackSlot *p, UmkaStackSlot *r)
{
th_font **ft = umkaGetParam(p, 0)->ptrVal;
char *path = conv_path(umkaGetParam(p, 1)->ptrVal);
Expand All @@ -133,9 +133,9 @@ umth_font_load(UmkaStackSlot *p, UmkaStackSlot *r)
free(path);
}

// fn umth_font_draw(font: Font, s: str, x: real, y: real, color: uint32, scale: real)
// fn umth_ttf_font_draw(font: TtfFont, s: str, x: real, y: real, color: uint32, scale: real)
static void
umth_font_draw(UmkaStackSlot *p, UmkaStackSlot *r)
umth_ttf_font_draw(UmkaStackSlot *p, UmkaStackSlot *r)
{
th_font *font = umkaGetParam(p, 0)->ptrVal;
const char *s = umkaGetParam(p, 1)->ptrVal;
Expand All @@ -147,9 +147,9 @@ umth_font_draw(UmkaStackSlot *p, UmkaStackSlot *r)
th_font_draw(font, s, x, y, color, scale);
}

// fn umth_font_measure(font: Font, s: str): th::Vf2
// fn umth_ttf_font_measure(font: TtfFont, s: str): th::Vf2
static void
umth_font_measure(UmkaStackSlot *p, UmkaStackSlot *r)
umth_ttf_font_measure(UmkaStackSlot *p, UmkaStackSlot *r)
{
th_font *font = umkaGetParam(p, 0)->ptrVal;
const char *s = umkaGetParam(p, 1)->ptrVal;
Expand Down Expand Up @@ -1441,9 +1441,9 @@ _th_umka_bind(void *umka)
umkaAddFunc(umka, "umth_rgb_uint32", &umth_rgb_uint32);

// font
umkaAddFunc(umka, "umth_font_load", &umth_font_load);
umkaAddFunc(umka, "umth_font_draw", &umth_font_draw);
umkaAddFunc(umka, "umth_font_measure", &umth_font_measure);
umkaAddFunc(umka, "umth_ttf_font_load", &umth_ttf_font_load);
umkaAddFunc(umka, "umth_ttf_font_draw", &umth_ttf_font_draw);
umkaAddFunc(umka, "umth_ttf_font_measure", &umth_ttf_font_measure);

// particles
umkaAddFunc(umka, "umth_particles_draw", &umth_particles_draw);
Expand Down
127 changes: 76 additions & 51 deletions src/staembed.c
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
#include "tophat.h"
#include "tophat.h"
const char *th_em_modulesrc[] = {
"\n"
"import (\n"
Expand Down Expand Up @@ -1218,6 +1218,7 @@ const char *th_em_modulesrc[] = {
"//~~\n"
"\n"
"import (\n"
"\t\"font.um\"\n"
"\t\"misc.um\"\n"
"\t\"rect.um\"\n"
"\t\"th.um\"\n"
Expand Down Expand Up @@ -1261,6 +1262,25 @@ const char *th_em_modulesrc[] = {
"\treturn {maxw * scale * 6 - scale, h * 6 * scale}\n"
"}\n"
"\n"
"type __PixelFont = struct { }\n"
"\n"
"fn (p: ^__PixelFont) draw*(text: str, pos: th::Vf2, color: uint32, scale: th::fu = 1.0) {\n"
"\tdrawText(text, pos, color, scale)\n"
"}\n"
"\n"
"fn (p: ^__PixelFont) measure*(text: str): th::Vf2 {\n"
"\treturn textSize(text, 1)\n"
"}\n"
"\n"
"fn (p: ^__PixelFont) validate*(): bool {\n"
"\treturn true\n"
"}\n"
"\n"
"//~~Pixel Font\n"
"// The `pixelFont` variable exposes the canvas pixel font as a generic font.\n"
"var pixelFont*: __PixelFont\n"
"//~~\n"
"\n"
"fn umth_canvas_draw_rect(color: uint32, r: rect::Rect)\n"
"//~~fn drawRect\n"
"// Draws a Rectangle.\n"
Expand Down Expand Up @@ -1302,7 +1322,7 @@ const char *th_em_modulesrc[] = {
"\tx := misc::maxf(a.x, b.x);\n"
"\ty := misc::maxf(a.y, b.y);\n"
"\treturn rect::Rect{\n"
"\t\tx,y, \n"
"\t\tx,y,\n"
"\t\tmisc::minf(a.x + a.w, b.x + b.w) - x,\n"
"\t\tmisc::minf(a.y + a.h, b.y + b.h) - y};\n"
"}\n"
Expand All @@ -1321,9 +1341,9 @@ const char *th_em_modulesrc[] = {
"\t}\n"
"\n"
"\tif debug {\n"
"\t\tdrawRectLines(th::red, r2, 0.1) \n"
"\t\tdrawRectLines(th::red, r2, 0.1)\n"
"\t}\n"
"\t\n"
"\n"
"\tumth_canvas_begin_scissor_rect(r2)\n"
"}\n"
"\n"
Expand Down Expand Up @@ -2029,45 +2049,53 @@ const char *th_em_modulesrc[] = {
"}\n"
"//~~\n"
"\n"
"//~~opaque Font\n"
"type Font* = struct { _: ^struct{} }\n"
"//~~\n"
"// TODO: should this be exported and documented?\n"
"type TtfFont* = struct { _: ^struct{} }\n"
"\n"
"fn umth_font_load(f: ^Font, path: str, size: th::fu, filter: Filter): th::ErrCode\n"
"//~~fn load\n"
"fn load*(path: str, size: th::fu, filter: Filter = Filter.linear): (Font, std::Err) {\n"
"//~~\n"
"\tvar f: Font\n"
"\tec := umth_font_load(&f, path, size, filter)\n"
"\treturn f, th::__errFromCode(ec)\n"
"}\n"
"fn umth_ttf_font_load(f: ^TtfFont, path: str, size: th::fu, filter: Filter): th::ErrCode\n"
"fn umth_ttf_font_draw(font: TtfFont, s: str, x: th::fu, y: th::fu, color: uint32, scale: th::fu)\n"
"fn umth_ttf_font_measure(font: TtfFont, s: str): th::Vf2\n"
"\n"
"//~~fn Font.validate\n"
"fn (f: ^Font) validate*(): bool {\n"
"//~~\n"
"fn (f: ^TtfFont) validate*(): bool {\n"
"\treturn f._ != null\n"
"}\n"
"\n"
"fn umth_font_draw(font: Font, s: str, x: th::fu, y: th::fu, color: uint32, scale: th::fu)\n"
"//~~fn Font.draw\n"
"fn (f: ^Font) draw*(text: str, pos: th::Vf2, color: uint32, scale: th::fu = 1.0) {\n"
"//~~\n"
"fn (f: ^TtfFont) draw*(text: str, pos: th::Vf2, color: uint32, scale: th::fu = 1.0) {\n"
"\tif !f.validate() {\n"
"\t\tth::__error(\"Invalid font\")\n"
"\t}\n"
"\tumth_font_draw(f^, text, pos.x, pos.y, color, scale)\n"
"\tumth_ttf_font_draw(f^, text, pos.x, pos.y, color, scale)\n"
"}\n"
"\n"
"fn umth_font_measure(font: Font, s: str): th::Vf2\n"
"//~~fn Font.measure\n"
"fn (f: ^Font) measure*(text: str): th::Vf2 {\n"
"//~~\n"
"fn (f: ^TtfFont) measure*(text: str): th::Vf2 {\n"
"\tif !f.validate() {\n"
"\t\tth::__error(\"Invalid font\")\n"
"\t\treturn {}\n"
"\t}\n"
"\n"
"\treturn umth_font_measure(f^, text)\n"
"\treturn umth_ttf_font_measure(f^, text)\n"
"}\n"
"\n"
"//~~interface Font\n"
"// A generic interface for fonts. Fonts can be loaded from file using\n"
"// `font.load`, or a built in canvas can be used from `canvas.pixelFont`.\n"
"type Font* = interface {\n"
"\t// Draw text to the viewport\n"
"\tdraw(text: str, pos: th::Vf2, color: uint32, scale: th::fu = 1.0)\n"
"\t// Return the dimensions of the text at scale 1\n"
"\tmeasure(text: str): th::Vf2\n"
"\t// Return true if the font is valid\n"
"\tvalidate(): bool\n"
"}\n"
"//~~\n"
"\n"
"//~~fn load\n"
"// Loads a font from a path and returns it.\n"
"fn load*(path: str, size: th::fu, filter: Filter = Filter.linear): (Font, std::Err) {\n"
"//~~\n"
"\tvar f: TtfFont\n"
"\tec := umth_ttf_font_load(&f, path, size, filter)\n"
"\treturn f, th::__errFromCode(ec)\n"
"}\n"
"",
"//~~\n"
Expand Down Expand Up @@ -4944,6 +4972,14 @@ const char *th_em_moduledocs[] = {
"\n"
"---------\n"
"\n"
"Pixel Font\n"
"\n"
"var pixelFont*: __PixelFont\n"
"\n"
"The `pixelFont` variable exposes the canvas pixel font as a generic font.\n"
"\n"
"---------\n"
"\n"
"fn drawRect\n"
"\n"
"fn drawRect*(color: uint32, r: rect::Rect) {\n"
Expand Down Expand Up @@ -5501,38 +5537,27 @@ const char *th_em_moduledocs[] = {
"\n"
"---------\n"
"\n"
"[1mopaque Font[0m\n"
"[1minterface Font[0m\n"
"\n"
"type Font* = struct { _: ^struct{} }\n"
"type Font* = interface {\n"
"\t// Draw text to the viewport\n"
"\tdraw(text: str, pos: th::Vf2, color: uint32, scale: th::fu = 1.0)\n"
"\t// Return the dimensions of the text at scale 1\n"
"\tmeasure(text: str): th::Vf2\n"
"\t// Return true if the font is valid\n"
"\tvalidate(): bool\n"
"}\n"
"\n"
"A generic interface for fonts. Fonts can be loaded from file using\n"
"`font.load`, or a built in canvas can be used from `canvas.pixelFont`.\n"
"\n"
"---------\n"
"\n"
"fn load\n"
"\n"
"fn load*(path: str, size: th::fu, filter: Filter = Filter.linear): (Font, std::Err) {\n"
"\n"
"\n"
"---------\n"
"\n"
"fn Font.validate\n"
"\n"
"fn (f: ^Font) validate*(): bool {\n"
"\n"
"\n"
"---------\n"
"\n"
"fn Font.draw\n"
"\n"
"fn (f: ^Font) draw*(text: str, pos: th::Vf2, color: uint32, scale: th::fu = 1.0) {\n"
"\n"
"\n"
"---------\n"
"\n"
"fn Font.measure\n"
"\n"
"fn (f: ^Font) measure*(text: str): th::Vf2 {\n"
"\n"
"Loads a font from a path and returns it.\n"
"\n"
"---------\n"
"\n"
Expand Down
26 changes: 23 additions & 3 deletions umka/canvas.um
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
//~~

import (
"font.um"
"misc.um"
"rect.um"
"th.um"
Expand Down Expand Up @@ -47,6 +48,25 @@ fn textSize*(text: str, scale: th::fu): th::Vf2 {
return {maxw * scale * 6 - scale, h * 6 * scale}
}

type __PixelFont = struct { }

fn (p: ^__PixelFont) draw*(text: str, pos: th::Vf2, color: uint32, scale: th::fu = 1.0) {
drawText(text, pos, color, scale)
}

fn (p: ^__PixelFont) measure*(text: str): th::Vf2 {
return textSize(text, 1)
}

fn (p: ^__PixelFont) validate*(): bool {
return true
}

//~~Pixel Font
// The `pixelFont` variable exposes the canvas pixel font as a generic font.
var pixelFont*: __PixelFont
//~~

fn umth_canvas_draw_rect(color: uint32, r: rect::Rect)
//~~fn drawRect
// Draws a Rectangle.
Expand Down Expand Up @@ -88,7 +108,7 @@ fn rectDiff(a, b: rect::Rect): rect::Rect {
x := misc::maxf(a.x, b.x);
y := misc::maxf(a.y, b.y);
return rect::Rect{
x,y,
x,y,
misc::minf(a.x + a.w, b.x + b.w) - x,
misc::minf(a.y + a.h, b.y + b.h) - y};
}
Expand All @@ -107,9 +127,9 @@ fn beginScissorRect*(r: rect::Rect, debug: bool = false) {
}

if debug {
drawRectLines(th::red, r2, 0.1)
drawRectLines(th::red, r2, 0.1)
}

umth_canvas_begin_scissor_rect(r2)
}

Expand Down
Loading

0 comments on commit 34ab8b9

Please sign in to comment.