summaryrefslogtreecommitdiffstats
path: root/virtual-programs/display
diff options
context:
space:
mode:
authorOmar Rizwan <omar@omar.website>2023-10-25 22:31:02 +0000
committerOmar Rizwan <omar@omar.website>2023-10-25 22:31:02 +0000
commitf8d2bb768ffbfbf12fdb27df28ea4e1fc707584a (patch)
treea740da541b9384cca0c8c4f01a1a74dda6de616f /virtual-programs/display
parenttext: Do text shaping in C (diff)
downloadfolk-f8d2bb768ffbfbf12fdb27df28ea4e1fc707584a.tar.gz
folk-f8d2bb768ffbfbf12fdb27df28ea4e1fc707584a.zip
text: Try using Tcl objects in text shaping to prevent conversion
Still slow (20fps for program list)
Diffstat (limited to 'virtual-programs/display')
-rw-r--r--virtual-programs/display/text.folk71
1 files changed, 33 insertions, 38 deletions
diff --git a/virtual-programs/display/text.folk b/virtual-programs/display/text.folk
index 451b9ce0..858a9dc7 100644
--- a/virtual-programs/display/text.folk
+++ b/virtual-programs/display/text.folk
@@ -3,48 +3,33 @@ On process "display" {
set cc [c create]
$cc include <math.h>
defineImageType $cc
- $cc struct GlyphInfo {
- float advance;
-
- float planeLeft;
- float planeBottom;
- float planeRight;
- float planeTop;
-
- float atlasLeft;
- float atlasBottom;
- float atlasRight;
- float atlasTop;
- }
$cc struct Font {
image_t atlasImage;
int gpuAtlasImage;
// TODO: This only handles ASCII, obviously.
- GlyphInfo glyphInfos[128];
+ Tcl_Obj* glyphInfos[128];
}
proc load {name} {
set csvFd [open "vendor/fonts/$name.csv" r]; set csv [read $csvFd]; close $csvFd
- set fields [list advance \
- planeLeft planeBottom planeRight planeTop \
- atlasLeft atlasBottom atlasRight atlasTop]
+ set fields [list ]
# HACK: Create list of null glyphs to initialize.
set glyphInfos [list]
for {set i 0} {$i < 128} {incr i} {
- set glyphInfo [dict create]
- foreach field $fields { dict set glyphInfo $field 0 }
- lappend glyphInfos $glyphInfo
+ lappend glyphInfos {}
}
foreach line [split $csv "\n"] {
set values [lassign [split $line ,] glyph]
if {![string is integer -strict $glyph]} { continue }
- set glyphInfo [dict create]
- foreach field $fields value $values {
- dict set glyphInfo $field $value
- }
- lset glyphInfos $glyph $glyphInfo
+ lassign $values advance \
+ planeLeft planeBottom planeRight planeTop \
+ atlasLeft atlasBottom atlasRight atlasTop
+ lset glyphInfos $glyph \
+ [list $advance \
+ [list $planeLeft $planeBottom $planeRight $planeTop] \
+ [list $atlasLeft $atlasBottom $atlasRight $atlasTop]]
}
set im [image load "[pwd]/vendor/fonts/$name.png"]
@@ -74,14 +59,18 @@ On process "display" {
if (ch >= sizeof(font->glyphInfos)/sizeof(font->glyphInfos[0])) {
ch = '?';
}
- GlyphInfo glyphInfo = font->glyphInfos[ch];
- x = x + glyphInfo.advance * em;
+ Tcl_Obj* glyphInfo = font->glyphInfos[ch];
+ Tcl_Obj* advanceObj; Tcl_ListObjIndex(NULL, glyphInfo, 0, &advanceObj);
+ double advance; Tcl_GetDoubleFromObj(NULL, advanceObj, &advance);
+ x = x + advance * em;
if (x > width) { width = x; }
}
return (vec2f) { width, y + em };
}
$cc proc textShape {Font* font char* text
float x0 float y0 float scale float radians} Tcl_Obj* {
+ Tcl_Obj* gpuAtlasImageSize = Tcl_ObjPrintf("%d %d", font->atlasImage.width, font->atlasImage.height);
+
vec2f extent = vec2f_rotate(textExtent(font, text, scale), radians);
float em = scale * 25.0;
@@ -100,18 +89,26 @@ On process "display" {
if (ch >= sizeof(font->glyphInfos)/sizeof(font->glyphInfos[0])) {
ch = '?';
}
- GlyphInfo glyphInfo = font->glyphInfos[ch];
+ Tcl_Obj* glyphInfo = font->glyphInfos[ch];
+ Tcl_Obj* advanceObj; Tcl_ListObjIndex(NULL, glyphInfo, 0, &advanceObj);
+ double advance; Tcl_GetDoubleFromObj(NULL, advanceObj, &advance);
if (ch != ' ') {
// Append to list of instances.
- Tcl_Obj* instance = Tcl_ObjPrintf("%d {%d %d} {%f %f %f %f} {%f %f %f %f} {%f %f} %f %f",
- font->gpuAtlasImage,
- font->atlasImage.width, font->atlasImage.height,
- glyphInfo.atlasLeft, glyphInfo.atlasBottom, glyphInfo.atlasRight, glyphInfo.atlasTop,
- glyphInfo.planeLeft, glyphInfo.planeBottom, glyphInfo.planeRight, glyphInfo.planeTop,
- p.x, p.y, radians, em);
+ Tcl_Obj* planeBounds; Tcl_ListObjIndex(NULL, glyphInfo, 1, &planeBounds);
+ Tcl_Obj* atlasBounds; Tcl_ListObjIndex(NULL, glyphInfo, 2, &atlasBounds);
+ Tcl_Obj* pv[] = {Tcl_NewDoubleObj(p.x), Tcl_NewDoubleObj(p.y)};
+ Tcl_Obj* pObj = Tcl_NewListObj(2, pv);
+ Tcl_Obj* args[] = {
+ Tcl_NewIntObj(font->gpuAtlasImage),
+ gpuAtlasImageSize,
+ atlasBounds,
+ planeBounds,
+ pObj, Tcl_NewDoubleObj(radians), Tcl_NewDoubleObj(em)
+ };
+ Tcl_Obj* instance = Tcl_NewListObj(sizeof(args)/sizeof(args[0]), args);
Tcl_ListObjAppendElement(NULL, instances, instance);
}
- p = vec2f_add(p, vec2f_rotate((vec2f) {glyphInfo.advance * em, 0}, radians));
+ p = vec2f_add(p, vec2f_rotate((vec2f) {advance * em, 0}, radians));
}
return instances;
}
@@ -184,9 +181,7 @@ On process "display" {
Wish $::thisProcess receives statements like \
[list /someone/ wishes to draw text with /...options/]
- set cc [c create]
-
- When /someone/ wishes to draw text with /...options/ {
+ When (non-capturing) /someone/ wishes to draw text with /...options/ {
if {[dict exists $options center]} {
lassign [dict get $options center] x0 y0
} else {