From 30106490c0e55a9eb166045954489f0e8e524c53 Mon Sep 17 00:00:00 2001 From: Amy Gale Ruth Bowersox Date: Sat, 7 Dec 2019 23:30:05 -0700 Subject: [PATCH] add text out capabilities using FreeType and the Inconsolata font --- scripts/tmp_main.py | 1 + src/Makefile | 7 ++-- src/ep_upiwin_tmp.c | 12 +++++++ src/fbprimitive.c | 31 +++++++++++++++++ src/fbprimitive.h | 1 + src/fontengine.c | 84 +++++++++++++++++++++++++++++++++++++++++++++ src/fontengine.h | 11 ++++++ src/main.c | 2 ++ 8 files changed, 146 insertions(+), 3 deletions(-) create mode 100644 src/fontengine.c create mode 100644 src/fontengine.h diff --git a/scripts/tmp_main.py b/scripts/tmp_main.py index 02799af..f57eaef 100644 --- a/scripts/tmp_main.py +++ b/scripts/tmp_main.py @@ -19,3 +19,4 @@ upiwin_tmp.filled_rectangle(110, 60, 150, 100, FBPRIMCLR_YELLOW, False) upiwin_tmp.rectangle(10, 110, 150, 150, FBPRIMCLR_WHITE, False) upiwin_tmp.line(10, 110, 150, 150, FBPRIMCLR_WHITE, False) upiwin_tmp.line(10, 150, 150, 110, FBPRIMCLR_WHITE, False) +upiwin_tmp.textout(10, 180, 'Amy was here!!!') diff --git a/src/Makefile b/src/Makefile index 9afd643..b757ace 100644 --- a/src/Makefile +++ b/src/Makefile @@ -1,7 +1,8 @@ -OBJS=main.o sysinput.o ep_init.o ep_upiwin.o ep_backlight.o ep_upiwin_tmp.o ep_util.o fbinit.o fbprimitive.o \ +OBJS=main.o sysinput.o ep_init.o ep_upiwin.o ep_backlight.o ep_upiwin_tmp.o ep_util.o fbinit.o fontengine.o 6fbprimitive.o \ log.o gpio.o msg_queue.o time_func.o config.o splash.o -LIBS=-lpython3.7m -lcrypt -lbcm2835 -lpthread -ldl -lutil -lm -CFLAGS=-I/usr/include/python3.7m -Wall -fstack-protector -fwrapv -fno-PIE -g -O3 -DDEBUG_ASSERT +LIBS=-lpython3.7m -lcrypt -lfreetype -lbcm2835 -lpthread -ldl -lutil -lm +CFLAGS=-I/usr/include/python3.7m -I/usr/include/freetype2 -I/usr/include/libpng16 \ + -Wall -fstack-protector -fwrapv -fno-PIE -g -O3 -DDEBUG_ASSERT LDFLAGS=-L/usr/lib/python3.7/config-3.7m-arm-linux-gnueabihf -Xlinker -export-dynamic -Wl,-O1 \ -Wl,-Bsymbolic-functions diff --git a/src/ep_upiwin_tmp.c b/src/ep_upiwin_tmp.c index 82fc446..339f72a 100644 --- a/src/ep_upiwin_tmp.c +++ b/src/ep_upiwin_tmp.c @@ -52,11 +52,23 @@ static PyObject *do_filled_rectangle(PyObject *self, PyObject *args) Py_RETURN_NONE; } +static PyObject *do_textout(PyObject *self, PyObject *args) +{ + INT32 x, y; + PSTR text; + + if (!PyArg_ParseTuple(args, "iis", &x, &y, &text)) + return NULL; + Fb_textout(x, y, text); + Py_RETURN_NONE; +} + static PyMethodDef UPIWIN_tmpMethods[] = { {"setpixel", do_setpixel, METH_VARARGS, "Set a single pixel on the display."}, {"line", do_line, METH_VARARGS, "Draw a line on the display."}, {"rectangle", do_rectangle, METH_VARARGS, "Draw a rectangle on the display."}, {"filled_rectangle", do_filled_rectangle, METH_VARARGS, "Draw a filled rectangle on the display."}, + {"textout", do_textout, METH_VARARGS, "Draw text on the display."}, {NULL, NULL, 0, NULL} }; diff --git a/src/fbprimitive.c b/src/fbprimitive.c index f434226..72d1ad0 100644 --- a/src/fbprimitive.c +++ b/src/fbprimitive.c @@ -1,3 +1,4 @@ +#include #include "wintype.h" #include "fbinit.h" @@ -112,3 +113,33 @@ void Fb_filled_rectangle(INT32 x1, INT32 y1, INT32 x2, INT32 y2, UINT16 color, B ps += Fb_Info->width; } } + +static void internal_textout(INT32 x, INT32 y, INT32 width, INT32 height, PBYTE gsbits) +{ + INT32 i, j; + BYTE b; + PUINT16 dptr, lbuf; + + if (((x + width) >= Fb_Info->width) || ((y + height) >= Fb_Info->height)) + return; + dptr = loc_from_coords(x, y); + lbuf = (PUINT16)alloca(width * sizeof(UINT16)); + for (i=0; i> 3) & 0x1F) << 11; + lbuf[i] |= ((UINT16)(b >> 2) & 0x3F) << 5; + lbuf[i] |= ((UINT16)(b >> 3) & 0x1F); + } + + memcpy(dptr, lbuf, width * sizeof(UINT16)); + dptr += Fb_Info->width; + } +} + +void Fb_textout(INT32 x, INT32 y, PCSTR pstr) +{ + FontEng_do_text_out(x, y, pstr, internal_textout); +} diff --git a/src/fbprimitive.h b/src/fbprimitive.h index 8f0ea8e..a9c4e52 100644 --- a/src/fbprimitive.h +++ b/src/fbprimitive.h @@ -17,5 +17,6 @@ extern UINT16 Fb_setpixel(INT32 x, INT32 y, UINT16 color, BOOL xor); extern void Fb_line(INT32 x1, INT32 y1, INT32 x2, INT32 y2, UINT16 color, BOOL xor); extern void Fb_rectangle(INT32 x1, INT32 y1, INT32 x2, INT32 y2, UINT16 color, BOOL xor); extern void Fb_filled_rectangle(INT32 x1, INT32 y1, INT32 x2, INT32 y2, UINT16 color, BOOL xor); +extern void Fb_textout(INT32 x, INT32 y, PCSTR pstr); #endif /* __FBPRIMITIVE_H_INCLUDED */ diff --git a/src/fontengine.c b/src/fontengine.c new file mode 100644 index 0000000..f8bfd7f --- /dev/null +++ b/src/fontengine.c @@ -0,0 +1,84 @@ +#include +#include FT_FREETYPE_H +#include "scode.h" +#include "config.h" +#include "log.h" +#include "fontengine.h" + +static FT_LIbrary library; +static FT_Face stdfont; + +static void fonteng_cleanup(void) +{ + FT_Done_Face(stdfont); + FT_Done_FreeType(library); +} + +HRESULT FontEng_setup(void) +{ + HRESULT hr = S_OK; + FT_Error err; + + err = FT_Init_FreeType(&library); + if (err != 0) + { + Log(LFATAL, "Unable to initialize Freetype (%d)", err); + return E_FAIL; + } + + err = FT_New_Face(library, "/usr/local/share/fonts/opentype/Inconsolata.otf", 0, &stdfont); + if (err != 0) + { + Log(LFATAL, "Unable to load font (%d)", err); + hr = E_FAIL; + goto error_0; + } + + err = FT_Set_Pixel_Sizes(stdfont, 0, 16); + if (err != 0) + { + Log(LFATAL, "Unable to set font size (%d)", err); + hr = E_FAIL; + goto error_1; + } + + hr = Config_exitfunc(fonteng_cleanup); + if (FAILED(hr)) + fonteng_cleanup(); + return hr; + +error_1: + FT_Done_Face(stdfont); +error_0: + FT_Done_FreeType(library); + return hr; +} + +HRESULT FontEng_do_text_out(INT32 x, INT32 y, PCSTR pstr, TEXTOUTFUNC renderfunc) +{ + HRESULT hr = S_OK; + FT_GlyphSlot slot = stdfont->glyph; + FT_UInt glyph_index; + FT_Error err; + + while (*pstr) + { + glyph_index = FT_Get_Char_Index(stdfont, *pstr++); + err = FT_Load_Glyph(stdfont, glyph_index, FT_LOAD_DEFAULT); + if (err != 0) + { + hr = E_FAIL; + break; + } + err = FT_Render_Glyph(stdfont->glyph, FT_RENDER_MODE_NORMAL); + if (err != 0) + { + hr = E_FAIL; + break; + } + (*renderfunc)(x, y, slot->bitmap.width, slot->bitmap.rows, slot->bitmap.buffer); + x += slot->advance.x >> 6; + y += slot->advance.y >> 6; + } + return hr; +} diff --git a/src/fontengine.h b/src/fontengine.h new file mode 100644 index 0000000..5fa9187 --- /dev/null +++ b/src/fontengine.h @@ -0,0 +1,11 @@ +#ifndef __FONTENGINE_H_INCLUDED +#define __FONTENGINE_H_INCLUDED + +#include "wintype.h" + +typedef void (*TEXTOUTFUNC)(INT32 x, INT32 y, INT32 width, INT32 height, PBYTE gsbits); + +extern HRESULT FontEng_setup(void); +extern HRESULT FontEng_do_text_out(INT32 x, INT32 y, PCSTR pstr, TEXTOUTFUNC renderfunc); + +#endif /* __FONTENGINE_H_INCLUDED */ diff --git a/src/main.c b/src/main.c index 9cadb84..957b5a0 100644 --- a/src/main.c +++ b/src/main.c @@ -31,6 +31,8 @@ int main(int argc, char *argv[]) return EXIT_SUCCESS; if (FAILED(Fb_setup())) return EXIT_FAILURE; + if (FAILED(FontEng_setup())) + return EXIT_FAILURE; if (FAILED(Gpio_setup())) return EXIT_FAILURE; if (FAILED(Epython_setup()))