Pārlūkot izejas kodu

wasm: support `vendor:stb/truetype` and `vendor:fontstash`

Laytan Laats 1 gadu atpakaļ
vecāks
revīzija
10c68a8951

+ 1 - 1
core/os/os_wasi.odin

@@ -96,7 +96,7 @@ wasi_match_preopen :: proc(path: string) -> (wasi.fd_t, string, bool) {
 
 	prefix_matches :: proc(prefix, path: string) -> bool {
 		// Empty is valid for any relative path.
-		if len(prefix) == 0 && len(path) > 0 && path[0] == '/' {
+		if len(prefix) == 0 && len(path) > 0 && path[0] != '/' {
 			return true
 		}
 

+ 3 - 17
vendor/fontstash/fontstash.odin

@@ -1,14 +1,14 @@
-//+build windows, linux, darwin
 //+vet !using-param
 package fontstash
 
 import "base:runtime"
+
 import "core:log"
-import "core:os"
 import "core:mem"
 import "core:math"
 import "core:strings"
 import "core:slice"
+
 import stbtt "vendor:stb/truetype"
 
 // This is a port from Fontstash into odin - specialized for nanovg
@@ -321,20 +321,6 @@ __AtlasAddWhiteRect :: proc(ctx: ^FontContext, w, h: int) -> bool {
 	return true
 }
 
-AddFontPath :: proc(
-	ctx: ^FontContext,
-	name: string,
-	path: string,
-) -> int {
-	data, ok := os.read_entire_file(path)
-
-	if !ok {
-		log.panicf("FONT: failed to read font at %s", path)
-	}
-
-	return AddFontMem(ctx, name, data, true)
-}
-
 // push a font to the font stack
 // optionally init with ascii characters at a wanted size
 AddFontMem :: proc(
@@ -1192,4 +1178,4 @@ EndState :: proc(using ctx: ^FontContext) {
 		}
 		__dirtyRectReset(ctx)
 	}
-}
+}

+ 20 - 0
vendor/fontstash/fontstash_os.odin

@@ -0,0 +1,20 @@
+//+build !js
+package fontstash
+
+import "core:log"
+import "core:os"
+
+AddFontPath :: proc(
+	ctx: ^FontContext,
+	name: string,
+	path: string,
+) -> int {
+	data, ok := os.read_entire_file(path)
+
+	if !ok {
+		log.panicf("FONT: failed to read font at %s", path)
+	}
+
+	return AddFontMem(ctx, name, data, true)
+}
+

BIN
vendor/stb/lib/stb_truetype_wasm.o


+ 4 - 0
vendor/stb/src/Makefile

@@ -6,6 +6,10 @@ else
 all: unix
 endif
 
+wasm:
+	mkdir -p ../lib
+	clang -c -Os --target=wasm32 -nostdlib stb_truetype_wasm.c -o ../lib/stb_truetype_wasm.o
+
 unix:
 	mkdir -p ../lib
 	$(CC) -c -O2 -Os -fPIC stb_image.c stb_image_write.c stb_image_resize.c stb_truetype.c stb_rect_pack.c stb_vorbis.c

+ 46 - 0
vendor/stb/src/stb_truetype_wasm.c

@@ -0,0 +1,46 @@
+#include <stddef.h>
+
+void *stbtt_malloc(size_t size);
+void stbtt_free(void *ptr);
+
+void stbtt_qsort(void* base, size_t num, size_t size, int (*compare)(const void*, const void*));
+
+double stbtt_floor(double x);
+double stbtt_ceil(double x);
+double stbtt_sqrt(double x);
+double stbtt_pow(double x, double y);
+double stbtt_fmod(double x, double y);
+double stbtt_cos(double x);
+double stbtt_acos(double x);
+double stbtt_fabs(double x);
+
+unsigned long stbtt_strlen(const char *str);
+
+void *memcpy(void *dst, const void *src, size_t count);
+void *memset(void *dst, int x, size_t count);
+
+#define STBRP_SORT stbtt_qsort
+#define STBRP_ASSERT(condition) ((void)0)
+
+#define STBTT_malloc(x,u)  ((void)(u),stbtt_malloc(x))
+#define STBTT_free(x,u)    ((void)(u),stbtt_free(x))
+
+#define STBTT_assert(condition) ((void)0)
+
+#define STBTT_ifloor(x)   ((int) stbtt_floor(x))
+#define STBTT_iceil(x)    ((int) stbtt_ceil(x))
+#define STBTT_sqrt(x)      stbtt_sqrt(x)
+#define STBTT_pow(x,y)     stbtt_pow(x,y)
+#define STBTT_fmod(x,y)    stbtt_fmod(x,y)
+#define STBTT_cos(x)       stbtt_cos(x)
+#define STBTT_acos(x)      stbtt_acos(x)
+#define STBTT_fabs(x)      stbtt_fabs(x)
+#define STBTT_strlen(x)    stbtt_strlen(x)
+#define STBTT_memcpy       memcpy
+#define STBTT_memset       memset
+
+#define STB_RECT_PACK_IMPLEMENTATION
+#include "stb_rect_pack.h"
+
+#define STB_TRUETYPE_IMPLEMENTATION
+#include "stb_truetype.h"

+ 2 - 0
vendor/stb/truetype/stb_truetype.odin

@@ -17,6 +17,8 @@ when LIB != "" {
 	}
 
 	foreign import stbtt { LIB }
+} else when ODIN_ARCH == .wasm32 || ODIN_ARCH == .wasm64p32 {
+	foreign import stbtt "../lib/stb_truetype_wasm.o"
 } else {
 	foreign import stbtt "system:stb_truetype"
 }

+ 92 - 0
vendor/stb/truetype/stb_truetype_wasm.odin

@@ -0,0 +1,92 @@
+//+build wasm32, wasm64p32
+package stb_truetype
+
+import "base:builtin"
+import "base:intrinsics"
+import "base:runtime"
+
+import "core:c"
+import "core:math"
+import "core:mem"
+import "core:sort"
+
+@(require, linkage="strong", link_name="stbtt_malloc")
+malloc :: proc "c" (size: uint) -> rawptr {
+	context = runtime.default_context()
+	ptr, _ := runtime.mem_alloc_non_zeroed(int(size))
+	return raw_data(ptr)
+}
+
+@(require, linkage="strong", link_name="stbtt_free")
+free :: proc "c" (ptr: rawptr) {
+	context = runtime.default_context()
+	builtin.free(ptr)
+}
+
+@(require, linkage="strong", link_name="stbtt_qsort")
+qsort :: proc "c" (base: rawptr, num: uint, size: uint, cmp: proc "c" (a, b: rawptr) -> i32) {
+	context = runtime.default_context()
+
+	Inputs :: struct {
+		base: rawptr,
+		num:  uint,
+		size: uint,
+		cmp:  proc "c" (a, b: rawptr) -> i32,
+	}
+	inputs := Inputs{base, num, size, cmp}
+
+	sort.sort({
+		collection = &inputs,
+		len = proc(it: sort.Interface) -> int {
+			inputs := (^Inputs)(it.collection)
+			return int(inputs.num)
+		},
+		less = proc(it: sort.Interface, i, j: int) -> bool {
+			inputs := (^Inputs)(it.collection)
+			a := rawptr(uintptr(inputs.base) + (uintptr(i) * uintptr(inputs.size)))
+			b := rawptr(uintptr(inputs.base) + (uintptr(j) * uintptr(inputs.size)))
+			return inputs.cmp(a, b) < 0
+		},
+		swap = proc(it: sort.Interface, i, j: int) {
+			inputs := (^Inputs)(it.collection)
+
+			a := rawptr(uintptr(inputs.base) + (uintptr(i) * uintptr(inputs.size)))
+			b := rawptr(uintptr(inputs.base) + (uintptr(j) * uintptr(inputs.size)))
+
+			tmp := intrinsics.alloca(inputs.size, runtime.DEFAULT_ALIGNMENT)
+			intrinsics.mem_copy_non_overlapping(tmp, a, inputs.size)
+			intrinsics.mem_copy_non_overlapping(a, b, inputs.size)
+			intrinsics.mem_copy_non_overlapping(b, tmp, inputs.size)
+		},
+	})
+}
+
+@(require, linkage="strong", link_name="stbtt_floor")
+floor :: proc "c" (x: f64) -> f64 { return math.floor(x) }
+@(require, linkage="strong", link_name="stbtt_ceil")
+ceil :: proc "c" (x: f64) -> f64 { return math.ceil(x) }
+@(require, linkage="strong", link_name="stbtt_sqrt")
+sqrt :: proc "c" (x: f64) -> f64 { return math.sqrt(x) }
+@(require, linkage="strong", link_name="stbtt_pow")
+pow :: proc "c" (x, y: f64) -> f64 { return math.pow(x, y) }
+
+@(require, linkage="strong", link_name="stbtt_fmod")
+fmod :: proc "c" (x, y: f64) -> f64 {
+	context = runtime.default_context();
+	// NOTE: only called in the `stbtt_GetGlyphSDF` code path.
+	panic("`math.round` is broken on 32 bit targets, see #3856")
+}
+
+@(require, linkage="strong", link_name="stbtt_cos")
+cos :: proc "c" (x: f64) -> f64 { return math.cos(x) }
+@(require, linkage="strong", link_name="stbtt_acos")
+acos :: proc "c" (x: f64) -> f64 { return math.acos(x) }
+@(require, linkage="strong", link_name="stbtt_fabs")
+fabs :: proc "c" (x: f64) -> f64 { return math.abs(x) }
+
+@(require, linkage="strong", link_name="stbtt_strlen")
+strlen :: proc "c" (str: cstring) -> c.ulong { return c.ulong(len(str)) }
+
+// NOTE: defined in runtime.
+// void *memcpy(void *dst, const void *src, size_t count);
+// void *memset(void *dst, int x, size_t count);