From 89e9c029e74a39f208344b52b32e99efef6026f3 Mon Sep 17 00:00:00 2001 From: TangoCash Date: Mon, 2 May 2016 22:05:33 +0200 Subject: [PATCH] adding truetype rendering widget --- Makefile.am | 1 + drivers.m4 | 2 +- drv_generic_graphic.c | 4 + widget_ttf.c | 319 ++++++++++++++++++++++++++++++++++++++++++ widget_ttf.h | 47 +++++++ 5 files changed, 372 insertions(+), 1 deletion(-) create mode 100644 widget_ttf.c create mode 100644 widget_ttf.h diff --git a/Makefile.am b/Makefile.am index 4ab4748..869e5f1 100644 --- a/Makefile.am +++ b/Makefile.am @@ -128,6 +128,7 @@ drv_X11.c \ font_6x8.h \ font_6x8_bold.h \ widget_image.c widget_image.h \ +widget_ttf.c widget_ttf.h \ \ lcd4linux_i2c.h \ \ diff --git a/drivers.m4 b/drivers.m4 index c3b9d46..3cd45e6 100644 --- a/drivers.m4 +++ b/drivers.m4 @@ -896,7 +896,7 @@ fi if test "$GRAPHIC" = "yes"; then DRIVERS="$DRIVERS drv_generic_graphic.o" if test "$has_gd" = "true"; then - DRIVERS="$DRIVERS widget_image.o" + DRIVERS="$DRIVERS widget_image.o widget_ttf.o" DRVLIBS="$DRVLIBS -lgd" AC_DEFINE(WITH_GD, 1, [GD library]) AC_DEFINE(WITH_IMAGE, 1, [image widget]) diff --git a/drv_generic_graphic.c b/drv_generic_graphic.c index e05542d..ccf1dee 100644 --- a/drv_generic_graphic.c +++ b/drv_generic_graphic.c @@ -69,6 +69,7 @@ #include "widget_icon.h" #include "widget_bar.h" #include "widget_image.h" +#include "widget_ttf.h" #include "rgb.h" #include "drv.h" #include "drv_generic.h" @@ -672,6 +673,9 @@ int drv_generic_graphic_init(const char *section, const char *driver) wc = Widget_Image; wc.draw = drv_generic_graphic_image_draw; widget_register(&wc); + wc = Widget_Truetype; + wc.draw = drv_generic_graphic_image_draw; + widget_register(&wc); #endif /* clear framebuffer but do not blit to display */ diff --git a/widget_ttf.c b/widget_ttf.c new file mode 100644 index 0000000..2229414 --- /dev/null +++ b/widget_ttf.c @@ -0,0 +1,319 @@ +/* truetype widget handling + * + * Copyright (C) 2016 TangoCash + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + */ + +/* + * exported functions: + * + * WIDGET_CLASS Widget_ttf + * the truetype widget + * + */ + + +#include "config.h" + +#include +#include +#include +#include +#include + +#ifdef HAVE_GD_GD_H +#include +#else +#ifdef HAVE_GD_H +#include +#else +#error "gd.h not found!" +#error "cannot compile image widget" +#endif +#endif + +#if GD2_VERS != 2 +#error "lcd4linux requires libgd version 2" +#error "cannot compile image widget" +#endif + +#include "debug.h" +#include "cfg.h" +#include "qprintf.h" +#include "property.h" +#include "timer_group.h" +#include "widget.h" +#include "widget_ttf.h" +#include "rgb.h" + +#ifdef WITH_DMALLOC +#include +#endif + + +static void widget_ttf_render(const char *Name, WIDGET_TTF * Image) +{ + int x, y; + int inverted; + gdImagePtr gdImage; + + int color; + int trans; + int brect[8]; + char *e; + unsigned long l; + unsigned char r,g,b; + char *fcolor; + char *text; + double size; + char *font; + char *err; + + + /* clear bitmap */ + if (Image->bitmap) { + int i; + for (i = 0; i < Image->height * Image->width; i++) { + RGBA empty = {.R = 0x00,.G = 0x00,.B = 0x00,.A = 0x00 }; + Image->bitmap[i] = empty; + } + } + + /* reload image only on first call or on explicit reload request */ + if (Image->gdImage == NULL || P2N(&Image->reload)) { + + /* free previous image */ + if (Image->gdImage) { + gdImageDestroy(Image->gdImage); + Image->gdImage = NULL; + } + + //replace with expression and use as text + text = P2S(&Image->value); + font = P2S(&Image->font); + size = P2N(&Image->size); + + err = gdImageStringFT(NULL,&brect[0],0,font,size,0.,0,0,text); + + x = brect[2]-brect[6] + 6; + y = brect[3]-brect[7] + 6; + Image->gdImage = gdImageCreateTrueColor(x,y); + gdImageSaveAlpha(Image->gdImage, 1); + + if (Image->gdImage == NULL) { + error("Warning: Image %s: Create failed!", Name); + return; + } + trans = gdImageColorAllocateAlpha(Image->gdImage, 0, 0, 0, 127); + gdImageFill(Image->gdImage, 0, 0, trans); + + fcolor = P2S(&Image->fcolor); + + l = strtoul(fcolor, &e, 16); + r = (l >> 16) & 0xff; + g = (l >> 8) & 0xff; + b = l & 0xff; + + color = gdImageColorAllocate(Image->gdImage, r, g, b); + + x = 3 - brect[6]; + y = 3 - brect[7]; + err = gdImageStringFT(Image->gdImage,&brect[0],color,font,size,0.0,x,y,text); + + } + + /* maybe resize bitmap */ + gdImage = Image->gdImage; + if (gdImage->sx > Image->width) { + Image->width = gdImage->sx; + free(Image->bitmap); + Image->bitmap = NULL; + } + if (gdImage->sy > Image->height) { + Image->height = gdImage->sy; + free(Image->bitmap); + Image->bitmap = NULL; + } + if (Image->bitmap == NULL && Image->width > 0 && Image->height > 0) { + int i = Image->width * Image->height * sizeof(Image->bitmap[0]); + Image->bitmap = malloc(i); + if (Image->bitmap == NULL) { + error("Warning: Image %s: malloc(%d) failed: %s", Name, i, strerror(errno)); + return; + } + for (i = 0; i < Image->height * Image->width; i++) { + RGBA empty = {.R = 0x00,.G = 0x00,.B = 0x00,.A = 0x00 }; + Image->bitmap[i] = empty; + } + } + + + /* finally really render it */ + inverted = P2N(&Image->inverted); + if (P2N(&Image->visible)) { + for (x = 0; x < gdImage->sx; x++) { + for (y = 0; y < gdImage->sy; y++) { + int p = gdImageGetTrueColorPixel(gdImage, x, y); + int a = gdTrueColorGetAlpha(p); + int i = y * Image->width + x; + Image->bitmap[i].R = gdTrueColorGetRed(p); + Image->bitmap[i].G = gdTrueColorGetGreen(p); + Image->bitmap[i].B = gdTrueColorGetBlue(p); + /* GD's alpha is 0 (opaque) to 127 (tranparanet) */ + /* our alpha is 0 (transparent) to 255 (opaque) */ + Image->bitmap[i].A = (a == 127) ? 0 : 255 - 2 * a; + if (inverted) { + Image->bitmap[i].R = 255 - Image->bitmap[i].R; + Image->bitmap[i].G = 255 - Image->bitmap[i].G; + Image->bitmap[i].B = 255 - Image->bitmap[i].B; + } + } + } + } +} + + +static void widget_ttf_update(void *Self) +{ + WIDGET *W = (WIDGET *) Self; + WIDGET_TTF *Image = W->data; + + /* process the parent only */ + if (W->parent == NULL) { + + /* evaluate properties */ + property_eval(&Image->value); + property_eval(&Image->size); + property_eval(&Image->font); + property_eval(&Image->fcolor); + property_eval(&Image->update); + property_eval(&Image->reload); + property_eval(&Image->visible); + property_eval(&Image->inverted); + + /* render image into bitmap */ + widget_ttf_render(W->name, Image); + + } + + /* finally, draw it! */ + if (W->class->draw) + W->class->draw(W); + + /* add a new one-shot timer */ + if (P2N(&Image->update) > 0) { + timer_add_widget(widget_ttf_update, Self, P2N(&Image->update), 1); + } +} + + + +int widget_ttf_init(WIDGET * Self) +{ + char *section; + WIDGET_TTF *Image; + + /* re-use the parent if one exists */ + if (Self->parent == NULL) { + + /* prepare config section */ + /* strlen("Widget:")=7 */ + section = malloc(strlen(Self->name) + 8); + strcpy(section, "Widget:"); + strcat(section, Self->name); + + Image = malloc(sizeof(WIDGET_TTF)); + memset(Image, 0, sizeof(WIDGET_TTF)); + + /* initial size */ + Image->width = 0; + Image->height = 0; + Image->bitmap = NULL; + + /* load properties */ + property_load(section, "expression", "Samsung", &Image->value); + property_load(section, "size", "40", &Image->size); + property_load(section, "font", NULL, &Image->font); + property_load(section, "fcolor", "ff0000", &Image->fcolor); + property_load(section, "update", "100", &Image->update); + property_load(section, "reload", "0", &Image->reload); + property_load(section, "visible", "1", &Image->visible); + property_load(section, "inverted", "0", &Image->inverted); + + /* sanity checks */ + if (!property_valid(&Image->font)) { + error("Warning: widget %s has no font", section); + } + + free(section); + Self->data = Image; + Self->x2 = Self->col + Image->width; + Self->y2 = Self->row + Image->height; + + } else { + + /* re-use the parent */ + Self->data = Self->parent->data; + + } + + /* just do it! */ + widget_ttf_update(Self); + + return 0; +} + + +int widget_ttf_quit(WIDGET * Self) +{ + if (Self) { + /* do not deallocate child widget! */ + if (Self->parent == NULL) { + if (Self->data) { + WIDGET_TTF *Image = Self->data; + if (Image->gdImage) { + gdImageDestroy(Image->gdImage); + Image->gdImage = NULL; + } + free(Image->bitmap); + property_free(&Image->value); + property_free(&Image->size); + property_free(&Image->font); + property_free(&Image->fcolor); + property_free(&Image->update); + property_free(&Image->reload); + property_free(&Image->visible); + property_free(&Image->inverted); + free(Self->data); + Self->data = NULL; + } + } + } + + return 0; + +} + + + +WIDGET_CLASS Widget_Truetype = { + .name = "Truetype", + .type = WIDGET_TYPE_XY, + .init = widget_ttf_init, + .draw = NULL, + .quit = widget_ttf_quit, +}; diff --git a/widget_ttf.h b/widget_ttf.h new file mode 100644 index 0000000..c385c45 --- /dev/null +++ b/widget_ttf.h @@ -0,0 +1,47 @@ +/* truetype widget handling + * + * Copyright (C) 2016 TangoCash + * + * This file is part of LCD4Linux. + * + * LCD4Linux is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * LCD4Linux is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + */ + + +#ifndef _WIDGET_TTF_H_ +#define _WIDGET_TTF_H_ + +#include "property.h" +#include "widget.h" +#include "rgb.h" + +typedef struct WIDGET_TTF { + void *gdImage; /* raw gd image */ + RGBA *bitmap; /* image bitmap */ + int width, height; /* size of the image */ + PROPERTY value; /* text to render */ + PROPERTY size; /* fontsize */ + PROPERTY font; /* path to font */ + PROPERTY fcolor; /* font color */ + PROPERTY update; /* update interval */ + PROPERTY reload; /* reload image on update? */ + PROPERTY visible; /* image visible? */ + PROPERTY inverted; /* image inverted? */ +} WIDGET_TTF; + +extern WIDGET_CLASS Widget_Truetype; + +#endif -- 2.39.5