aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorjaseg <jaseg@jaseg.net>2014-03-07 00:49:16 +0100
committerjaseg <jaseg@jaseg.net>2014-03-07 00:49:16 +0100
commitd16223fd257ccc1d7060e372eb3d950cf68f8d37 (patch)
tree6484e177faff92ed77b2f91acaadaba33131b44d
parent7878aa1d455ab24d0336fc68eb09f726bcba10b2 (diff)
downloadmatelight-d16223fd257ccc1d7060e372eb3d950cf68f8d37.tar.gz
matelight-d16223fd257ccc1d7060e372eb3d950cf68f8d37.tar.bz2
matelight-d16223fd257ccc1d7060e372eb3d950cf68f8d37.zip
Modified text rendering to something frame based
-rw-r--r--host/Makefile4
-rw-r--r--host/bdf.c (renamed from host/main.c)82
-rw-r--r--host/bdf.h11
-rw-r--r--host/font.c14
-rw-r--r--host/font.h2
-rw-r--r--host/main.h10
-rwxr-xr-xhost/server.py51
7 files changed, 89 insertions, 85 deletions
diff --git a/host/Makefile b/host/Makefile
index 8abc88a..85536f5 100644
--- a/host/Makefile
+++ b/host/Makefile
@@ -5,8 +5,8 @@ all: libml libbdf
libml: usb.c color.c color.h
gcc -shared -fPIC -std=gnu11 -Wall -lm -lusb-1.0 -o libml.so -g usb.c color.c
-libbdf: main.c font.c font.h color.c color.h
- gcc -shared -fPIC -std=gnu11 -Wall -lm -o libbdf.so -g main.c font.c color.c
+libbdf: bdf.c font.c font.h color.c color.h
+ gcc -shared -fPIC -std=gnu11 -Wall -lm -o libbdf.so -g bdf.c font.c color.c
clean:
rm libbdf.so libml.so
diff --git a/host/main.c b/host/bdf.c
index d8cb371..e6ab827 100644
--- a/host/main.c
+++ b/host/bdf.c
@@ -1,6 +1,6 @@
#include "config.h"
-#include "main.h"
+#include "bdf.h"
#include "color.h"
#include "font.h"
#include <stdint.h>
@@ -17,20 +17,11 @@
#include <netinet/in.h>
#include <unistd.h>
-
-void free_framebuffer(framebuffer_t *fb){
- free(fb->data);
- free(fb);
-}
-
/* CAUTION: REQUIRES INPUT TO BE \0-TERMINATED
* ...also, it does a hardcoded setlocale of LC_CTYPE to en_US.utf8 for... reasons. */
-framebuffer_t *framebuffer_render_text(char *s, glyphtable_t *glyph_table){
- unsigned int len = strlen(s);
-
- color_t *gbuf = NULL;
- unsigned int gbufwidth = 0;
- unsigned int gbufheight = 0;
+int framebuffer_get_text_bounds(char *s, glyphtable_t *glyph_table, size_t *outw, size_t *outh){
+ size_t gbufwidth = 0;
+ size_t gbufheight = 0;
char *p = s;
/* Calculate screen width of string prior to allocating memory for the frame buffer */
@@ -80,19 +71,31 @@ framebuffer_t *framebuffer_render_text(char *s, glyphtable_t *glyph_table){
gbufwidth += g->width;
}
- /* For easier rendering on the terminal, round up to multiples of two */
- gbufheight += gbufheight&1;
+ *outw = gbufwidth;
+ *outh = gbufheight;
+ return 0;
+error:
+ return 1;
+}
+
+/* CAUTION: REQUIRES INPUT TO BE \0-TERMINATED
+ * ...also, it does a hardcoded setlocale of LC_CTYPE to en_US.utf8 for... reasons. */
+/* Render the string beginning from the specified x offset (in pixels) */
+int framebuffer_render_text(char *s, glyphtable_t *glyph_table, color_t *gbuf, size_t gbufwidth, size_t gbufheight, size_t offx){
+ unsigned int len = strlen(s);
+ char *p = s;
- size_t gbufsize = gbufwidth*gbufheight;
- gbuf = calloc(gbufsize, sizeof(color_t));
- if(!gbuf){
- fprintf(stderr, "Cannot malloc() %zu bytes.\n", gbufsize*sizeof(color_t));
+ if(!setlocale(LC_CTYPE, "en_US.utf8")){
+ fprintf(stderr, "Cannot set locale\n");
goto error;
}
- memset(gbuf, 0, gbufsize*sizeof(color_t));
+
+ memset(gbuf, 0, gbufwidth*gbufheight*sizeof(color_t));
unsigned int x = 0;
+ wchar_t c;
p = s;
+ mbstate_t ps = {0};
memset(&ps, 0, sizeof(mbstate_t));
struct {
color_t fg;
@@ -279,32 +282,29 @@ framebuffer_t *framebuffer_render_text(char *s, glyphtable_t *glyph_table){
color_t bg = inv ? style.bg : style.fg;
glyph_t *g = glyph_table->data[c];
- render_glyph(g, gbuf, gbufwidth, x, 0, fg, bg);
- if(style.strikethrough || style.underline){
- int sty = gbufheight/2;
- /* g->y usually is a negative index of the glyph's baseline measured from the glyph's bottom */
- int uly = gbufheight + g->y;
- for(int i=0; i<g->width; i++){
- if(style.strikethrough)
- gbuf[sty*gbufwidth + x + i] = fg;
- if(style.underline)
- gbuf[uly*gbufwidth + x + i] = fg;
+ /* Is the glyph within the buffer's bounds? */
+ if(x+g->width > offx && x < offx+gbufwidth){
+ /* x-offx might be negative down to -g->width+1, but that's ok */
+ render_glyph(g, gbuf, gbufwidth, x-offx, 0, fg, bg);
+ if(style.strikethrough || style.underline){
+ int sty = gbufheight/2;
+ /* g->y usually is a negative index of the glyph's baseline measured from the glyph's bottom */
+ int uly = gbufheight + g->y;
+ for(int i=0; i<g->width; i++){
+ if(x+i >= offx){ /* Stay within the frame buffer's bounds */
+ if(style.strikethrough)
+ gbuf[sty*gbufwidth + x + i - offx] = fg;
+ if(style.underline)
+ gbuf[uly*gbufwidth + x + i - offx] = fg;
+ }
+ }
}
}
x += g->width;
}
- framebuffer_t *fb = malloc(sizeof(framebuffer_t));
- if(!fb){
- fprintf(stderr, "Cannot malloc() %zu bytes.\n", sizeof(framebuffer_t));
- goto error;
- }
- fb->w = gbufwidth;
- fb->h = gbufheight;
- fb->data = gbuf;
- return fb;
-error:
- free(gbuf);
return 0;
+error:
+ return 1;
}
void console_render_buffer(color_t *data, size_t w, size_t h){
diff --git a/host/bdf.h b/host/bdf.h
new file mode 100644
index 0000000..c81277e
--- /dev/null
+++ b/host/bdf.h
@@ -0,0 +1,11 @@
+#ifndef __MAIN_H__
+#define __MAIN_H__
+
+#include "color.h"
+#include "font.h"
+
+int framebuffer_get_text_bounds(char *s, glyphtable_t *glyph_table, size_t *outw, size_t *outh);
+int framebuffer_render_text(char *s, glyphtable_t *glyph_table, color_t *gbuf, size_t gbufwidth, size_t gbufheight, size_t offx);
+void console_render_buffer(color_t *data, size_t w, size_t h);
+
+#endif//__MAIN_H__
diff --git a/host/font.c b/host/font.c
index ee9adb3..c1f1d22 100644
--- a/host/font.c
+++ b/host/font.c
@@ -6,7 +6,8 @@
#include <string.h>
#include <errno.h>
-void render_glyph(glyph_t *g, color_t *buf, unsigned int bufwidth, unsigned int offx, unsigned int offy, color_t fg, color_t bg){
+/* Clips at buffer bounds */
+void render_glyph(glyph_t *g, color_t *buf, unsigned int bufwidth, int offx, unsigned int offy, color_t fg, color_t bg){
unsigned int bitmap_row_width = g->width/8;
uint8_t *bitmap = ((uint8_t *)g) + sizeof(glyph_t);
for(unsigned int y=0; y < g->height; y++){
@@ -16,10 +17,13 @@ void render_glyph(glyph_t *g, color_t *buf, unsigned int bufwidth, unsigned int
data |= bitmap[y*bitmap_row_width+i];
}
color_t *p = buf + (offy+y)*bufwidth + offx;
- for(unsigned int x=0; x < g->width; x++){
- color_t c = (data&(1<<(g->width-1))) ? fg : bg;
- *p++ = c;
- data <<= 1;
+ /* Take care to only render what's within the framebuffer's bounds */
+ for(unsigned int x=0; (x < g->width) && (offx+x < bufwidth); x++){
+ if(offx + x >= 0){
+ color_t c = (data&(1<<(g->width-1))) ? fg : bg;
+ *p++ = c;
+ data <<= 1;
+ }
}
}
}
diff --git a/host/font.h b/host/font.h
index e9fbb35..ad7f851 100644
--- a/host/font.h
+++ b/host/font.h
@@ -30,6 +30,6 @@ glyphtable_t *read_bdf(FILE *f);
void free_glyphtable(glyphtable_t *glyph_table);
// Requires buf to point to a buffer at least of size glyph->width*glyph->height.
-void render_glyph(glyph_t *glyph, color_t *buf, unsigned int bufwidth, unsigned int offx, unsigned int offy, color_t fg, color_t bg);
+void render_glyph(glyph_t *g, color_t *buf, unsigned int bufwidth, int offx, unsigned int offy, color_t fg, color_t bg);
#endif//__FONT_H__
diff --git a/host/main.h b/host/main.h
deleted file mode 100644
index 5ace45e..0000000
--- a/host/main.h
+++ /dev/null
@@ -1,10 +0,0 @@
-#ifndef __MAIN_H__
-#define __MAIN_H__
-
-#include "color.h"
-#include "font.h"
-
-framebuffer_t *framebuffer_render_text(char *s, glyphtable_t *glyph_table);
-void console_render_buffer(color_t *data, size_t w, size_t h);
-
-#endif//__MAIN_H__
diff --git a/host/server.py b/host/server.py
index 56002fa..679b13b 100755
--- a/host/server.py
+++ b/host/server.py
@@ -7,7 +7,7 @@ from itertools import product, cycle
import threading
import random
-from ctypes import CDLL, POINTER, c_void_p, Structure, c_uint8, c_size_t, cast, addressof
+from ctypes import *
import numpy as np
@@ -26,20 +26,26 @@ class FRAMEBUFFER(Structure):
bdf = CDLL('./libbdf.so')
bdf.read_bdf_file.restype = c_void_p
bdf.framebuffer_render_text.restype = POINTER(FRAMEBUFFER)
+bdf.framebuffer_render_text.argtypes= [c_char_p, c_void_p, c_void_p, c_size_t, c_size_t, c_size_t]
unifont = bdf.read_bdf_file('unifont.bdf')
-def render_text(text):
+def compute_text_bounds(text):
assert unifont
- fb = bdf.framebuffer_render_text(bytes(str(text), 'UTF-8'), unifont)
- fbd = fb.contents
- buf = np.ctypeslib.as_array(cast(fbd.data, POINTER(c_uint8)), shape=(fbd.h, fbd.w, 4))
- # Set data pointer to NULL before freeing framebuffer struct to prevent free_framebuffer from also freeing the data
- # buffer that is now used by numpy
- #bdf.console_render_buffer(fb)
- fbd.data = cast(c_void_p(), POINTER(COLOR))
- bdf.free_framebuffer(fb)
- return buf
+ textbytes = bytes(str(text), 'UTF-8')
+ textw, texth = c_size_t(0), c_size_t(0)
+ res = bdf.framebuffer_get_text_bounds(textbytes, unifont, byref(textw), byref(texth))
+ if res:
+ raise ValueError('Invalid text')
+ return textw.value, texth.value
+
+def render_text(text, offset):
+ cbuf = create_string_buffer(FRAME_SIZE*sizeof(COLOR))
+ textbytes = bytes(str(text), 'UTF-8')
+ res = bdf.framebuffer_render_text(textbytes, unifont, cbuf, DISPLAY_WIDTH, DISPLAY_HEIGHT, offset)
+ if res:
+ raise ValueError('Invalid text')
+ return np.ctypeslib.as_array(cast(cbuf, POINTER(c_uint8)), shape=(DISPLAY_WIDTH, DISPLAY_HEIGHT, 4))
printlock = threading.Lock()
@@ -55,19 +61,11 @@ def printframe(fb):
def scroll(text):
""" Returns whether it could scroll all the text uninterrupted """
log('Scrolling', text)
- fb = render_text(text);
- h,w,_ = fb.shape
+ w,h = compute_text_bounds(text)
for i in range(-DISPLAY_WIDTH,w+1):
-# if current_entry.entrytype == 'udp' or (textqueue and current_entry in defaulttexts):
-# log('Aborting rendering due to new input')
-# return False
- leftpad = np.zeros((DISPLAY_HEIGHT, max(-i, 0), 4), dtype=np.uint8)
- framedata = fb[:, max(0, i):min(i+DISPLAY_WIDTH, w)]
- rightpad = np.zeros((DISPLAY_HEIGHT, min(DISPLAY_WIDTH, max(0, i+DISPLAY_WIDTH-w)), 4), dtype=np.uint8)
- dice = np.concatenate((leftpad, framedata, rightpad), 1)
- sendframe(dice)
- printframe(dice)
- fb = render_text(text);
+ fb = render_text(text, i);
+ sendframe(fb)
+ printframe(fb)
return True
QueueEntry = namedtuple('QueueEntry', ['entrytype', 'remote', 'timestamp', 'text'])
@@ -80,7 +78,7 @@ textqueue = []
def log(*args):
printlock.acquire()
- print(strftime('[%m-%d %H:%M:%S]'), ' '.join(str(arg) for arg in args), '\x1B[0m')
+ print(strftime('\x1B[93m[%m-%d %H:%M:%S]\x1B[0m'), ' '.join(str(arg) for arg in args), '\x1B[0m')
printlock.release()
class MateLightUDPHandler(BaseRequestHandler):
@@ -107,7 +105,7 @@ class MateLightUDPHandler(BaseRequestHandler):
addr = self.client_address[0]
conn = QueueEntry('udp', addr, timestamp, '')
if addr not in conns:
- log('New UDP connection from', addr)
+ log('\x1B[91mNew UDP connection from\x1B[0m', addr)
current_entry = conn
conns[addr] = current_entry
if current_entry.entrytype == 'udp' and current_entry.remote == addr:
@@ -127,7 +125,7 @@ class MateLightTCPTextHandler(BaseRequestHandler):
if len(data) > 140:
self.request.sendall('TOO MUCH INFORMATION!\n')
return
- log('Text from {}: {}\x1B[0m'.format(addr, data))
+ log('\x1B[95mText from\x1B[0m {}: {}\x1B[0m'.format(addr, data))
textqueue.append(QueueEntry('text', addr, timestamp, data))
self.request.sendall(b'KTHXBYE!\n')
@@ -159,6 +157,7 @@ if __name__ == '__main__':
current_entry = next(defaulttexts)
if current_entry.entrytype != 'udp' and textqueue:
current_entry = textqueue[0]
+ log('\x1B[92mScrolling\x1B[0m', current_entry.text)
if current_entry.entrytype == 'udp':
if time() - current_entry.timestamp > UDP_TIMEOUT:
current_entry = next(defaulttexts)