Add PNG connection type and Freetype 2 font rendering to glcd driver. The PNG
image writer is for debugging only. The Freetype font renderer still misses some features (e.g. big numbers, character encoding, non-standard cell size).
This commit is contained in:
@@ -13,6 +13,8 @@ v0.5dev (ongoing development)
|
||||
+ new driver: vlsys_m428 driver for Moneual MonCaso 320 (W. Hauck)
|
||||
* hd44780/serial: Fix handling of keys for LoS-Panel (M. Kirchner)
|
||||
* hd44780/serial: Change backlight handling (see commit message)
|
||||
+ glcd driver: Add FreeType 2 rendering support (B. Walle and M. Dolze)
|
||||
+ glcd driver: New connection type PNG, writes framebuffer as PNG image
|
||||
|
||||
v0.5.5
|
||||
+ sed1330 driver: Add support for HG25504 (L. Lagendijk)
|
||||
|
||||
@@ -378,6 +378,20 @@ ConnectionType=t6963
|
||||
# legal: yes, no]
|
||||
#delayBus=no
|
||||
|
||||
# If LCDproc has been compiled with FreeType 2 support this option can be used
|
||||
# to turn if off intentionally. [default: yes; legal: yes, no]
|
||||
#useFT2=no
|
||||
|
||||
# Path to font file to use for FreeType rendering. This font must be monospace
|
||||
# and should contain some special Unicode characters like arrows (Andale Mono
|
||||
# is recommended and can be fetched at http://corefonts.sf.net).
|
||||
normal_font=/usr/local/lib/X11/fonts/TTF/andalemo.ttf
|
||||
|
||||
# Some fonts miss the Unicode characters used to represent icons. In this case
|
||||
# the built-in 5x8 font can used if this option is turned off. [default: yes;
|
||||
# legal: yes, no]
|
||||
#fontHasIcons=no
|
||||
|
||||
|
||||
|
||||
## glcdlib meta driver for graphical LCDs ##
|
||||
|
||||
+54
-1
@@ -170,6 +170,9 @@ dnl else
|
||||
if test "$ac_cv_port_have_lpt" = yes ; then
|
||||
GLCD_DRIVERS="$GLCD_DRIVERS glcd-t6963.o t6963_low.o"
|
||||
fi
|
||||
if test "$enable_libpng" = yes ; then
|
||||
GLCD_DRIVERS="$GLCD_DRIVERS glcd-glcd-png.o"
|
||||
fi
|
||||
DRIVERS="$DRIVERS glcd${SO}"
|
||||
actdrivers=["$actdrivers glcd"]
|
||||
;;
|
||||
@@ -1057,7 +1060,7 @@ AC_DEFUN([AX_CXXFLAGS_GCC_OPTION],[ifelse(m4_bregexp([$2],[-]),-1,
|
||||
[AX_CXXFLAGS_GCC_OPTION_NEW($@)],[AX_CXXFLAGS_GCC_OPTION_OLD($@)])])
|
||||
|
||||
dnl
|
||||
dnl Check if system has SA_RESTART defined. Copied from GNU's make configure.
|
||||
dnl Check if system has SA_RESTART defined. Copied from GNUs make configure.
|
||||
dnl
|
||||
AC_DEFUN([LCD_SA_RESTART], [
|
||||
AC_CACHE_CHECK([for SA_RESTART], lcd_cv_sa_restart, [
|
||||
@@ -1070,3 +1073,53 @@ if test "$lcd_cv_sa_restart" != no; then
|
||||
[Define to 1 if <signal.h> defines the SA_RESTART constant.])
|
||||
fi
|
||||
])
|
||||
|
||||
dnl
|
||||
dnl Check for PNG library
|
||||
dnl
|
||||
AC_DEFUN([LCD_PNG_LIB], [
|
||||
AC_MSG_CHECKING([if PNG support has been enabled]);
|
||||
AC_ARG_ENABLE(libpng,
|
||||
[AS_HELP_STRING([--disable-png],[disable PNG support using libpng])],
|
||||
[ if test "$enableval" != "no"; then
|
||||
enable_libpng=yes
|
||||
fi ],
|
||||
[ enable_libpng=yes ]
|
||||
)
|
||||
AC_MSG_RESULT($enable_libpng)
|
||||
|
||||
if test "$enable_libpng" = "yes"; then
|
||||
AC_PATH_PROG([_png_config], [libpng-config])
|
||||
_libpng_save_libs=$LIBS
|
||||
_libpng_save_cflags=$CFLAGS
|
||||
|
||||
if test x$_png_config != "x" ; then
|
||||
_libpng_try_libs=`$_png_config --ldflags`
|
||||
_libpng_try_cflags=`$_png_config --cflags`
|
||||
fi
|
||||
|
||||
LIBS="$LIBS $_libpng_try_libs"
|
||||
CFLAGS="$CFLAGS $_libpng_try_cflags"
|
||||
|
||||
AC_MSG_CHECKING([whether libpng is present and sane])
|
||||
AC_LINK_IFELSE([AC_LANG_PROGRAM([#include <png.h>],[
|
||||
png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
|
||||
])],enable_libpng=yes,enable_libpng=no)
|
||||
AC_MSG_RESULT([$enable_libpng])
|
||||
|
||||
if test "$enable_libpng" = "yes" ; then
|
||||
AC_DEFINE(HAVE_LIBPNG, [1], [Define to 1 if you have libpng])
|
||||
AC_SUBST(LIBPNG_CFLAGS, $_libpng_try_cflags)
|
||||
AC_SUBST(LIBPNG_LIBS, $_libpng_try_libs)
|
||||
fi
|
||||
|
||||
LIBS=$_libpng_save_libs
|
||||
CFLAGS=$_libpng_save_cflags
|
||||
|
||||
unset _libpng_save_libs
|
||||
unset _libpng_save_cflags
|
||||
unset _libpng_try_libs
|
||||
unset _libpng_try_cflags
|
||||
unset _png_config
|
||||
fi
|
||||
])
|
||||
|
||||
+25
-1
@@ -254,7 +254,7 @@ AC_MSG_CHECKING([if libusb support has been enabled]);
|
||||
AC_ARG_ENABLE(libusb,
|
||||
[AS_HELP_STRING([--disable-libusb],[disable USB support using libusb])],
|
||||
[ if test "$enableval" != "no"; then
|
||||
enable_libusb="yes"
|
||||
enable_libusb=yes
|
||||
fi ],
|
||||
[ enable_libusb=yes ]
|
||||
)
|
||||
@@ -316,6 +316,30 @@ fi
|
||||
AC_SUBST(LIBHID_LIBS)
|
||||
AC_SUBST(LIBHID_CFLAGS)
|
||||
|
||||
# PNG library
|
||||
LCD_PNG_LIB
|
||||
|
||||
dnl ######################################################################
|
||||
dnl freetype support
|
||||
dnl ######################################################################
|
||||
AC_MSG_CHECKING([if freetype support has been enabled]);
|
||||
AC_ARG_ENABLE(freetype,
|
||||
[AS_HELP_STRING([--disable-freetype],[disable freetype support])],
|
||||
[ if test "$enableval" != "no"; then
|
||||
enable_freetype=yes
|
||||
fi ],
|
||||
[ enable_freetype=yes ]
|
||||
)
|
||||
AC_MSG_RESULT($enable_freetype)
|
||||
|
||||
if test "$enable_freetype" = "yes"; then
|
||||
ifdef([AC_CHECK_FT2],
|
||||
[AC_CHECK_FT2([],
|
||||
[AC_DEFINE(HAVE_FT2, [1], [Define to 1 if you have freetype])],
|
||||
[enable_freetype=no])],
|
||||
[AC_MSG_WARN([freetype does not seem to be installed])])
|
||||
fi
|
||||
|
||||
dnl ######################################################################
|
||||
dnl ethlcd support
|
||||
dnl ######################################################################
|
||||
|
||||
@@ -26,6 +26,7 @@ EXTRA_PROGRAMS = bayrad CFontz CFontzPacket curses debug CwLnx ea65 EyeboxOne g1
|
||||
noinst_LIBRARIES = libLCD.a libbignum.a
|
||||
|
||||
g15_CFLAGS = @LIBUSB_CFLAGS@ $(AM_CFLAGS)
|
||||
glcd_CFLAGS = @FT2_CFLAGS@ @LIBPNG_CFLAGS@ $(AM_CFLAGS)
|
||||
hd44780_CFLAGS = @LIBUSB_CFLAGS@ @LIBFTDI_CFLAGS@ $(AM_CFLAGS)
|
||||
i2500vfd_CFLAGS = @LIBFTDI_CFLAGS@ $(AM_CFLAGS)
|
||||
IOWarrior_CFLAGS = @LIBUSB_CFLAGS@ $(AM_CFLAGS)
|
||||
@@ -42,8 +43,8 @@ CFontzPacket_LDADD = libLCD.a libbignum.a
|
||||
curses_LDADD = @LIBCURSES@
|
||||
CwLnx_LDADD = libLCD.a libbignum.a
|
||||
g15_LDADD = @LIBG15@
|
||||
glcd_LDADD = libLCD.a @GLCD_DRIVERS@
|
||||
glcd_DEPENDENCIES = @GLCD_DRIVERS@
|
||||
glcd_LDADD = libLCD.a @GLCD_DRIVERS@ @FT2_LIBS@ @LIBPNG_LIBS@
|
||||
glcd_DEPENDENCIES = @GLCD_DRIVERS@ glcd-glcd-render.o
|
||||
glcdlib_LDADD = @LIBGLCD@
|
||||
glk_LDADD = libbignum.a
|
||||
hd44780_LDADD = libLCD.a @HD44780_DRIVERS@ @LIBUSB_LIBS@ @LIBFTDI_LIBS@ libbignum.a
|
||||
@@ -87,8 +88,8 @@ debug_SOURCES = lcd.h report.h debug.c debug.h
|
||||
ea65_SOURCES = lcd.h ea65.h ea65.c report.h
|
||||
EyeboxOne_SOURCES = lcd.h lcd_lib.h EyeboxOne.c EyeboxOne.h report.h
|
||||
g15_SOURCES = lcd.h lcd_lib.h g15.h g15-num.c g15.c report.h
|
||||
glcd_SOURCES = lcd.h report.h glcd_drv.c glcd_drv.h glcd-low.h glcd-drivers.h
|
||||
EXTRA_glcd_SOURCES = glcd-t6963.c glcd-t6963.h t6963_low.c t6963_low.h
|
||||
glcd_SOURCES = lcd.h report.h glcd_drv.c glcd_drv.h glcd-low.h glcd-drivers.h glcd-render.c glcd-render.h
|
||||
EXTRA_glcd_SOURCES = glcd-t6963.c glcd-t6963.h t6963_low.c t6963_low.h glcd-png.c glcd-png.h
|
||||
glcdlib_SOURCES = lcd.h lcd_lib.h glcdlib.h glcdlib.c report.h
|
||||
glk_SOURCES = lcd.h glk.c glk.h glkproto.c glkproto.h report.h
|
||||
hd44780_SOURCES = lcd.h lcd_lib.h hd44780.h hd44780.c hd44780-drivers.h hd44780-low.h hd44780-charmap.h report.h adv_bignum.h
|
||||
|
||||
@@ -16,10 +16,14 @@
|
||||
#ifdef HAVE_PCSTYLE_LPT_CONTROL
|
||||
# include "glcd-t6963.h"
|
||||
#endif
|
||||
#ifdef HAVE_LIBPNG
|
||||
# include "glcd-png.h"
|
||||
#endif
|
||||
|
||||
/* symbolic names for connection types */
|
||||
#define GLCD_CT_UNKNOWN 0
|
||||
#define GLCD_CT_T6963 1
|
||||
#define GLCD_CT_PNG 2
|
||||
|
||||
/** Structure linking symbolic names to initialization routines */
|
||||
typedef struct ConnectionMapping {
|
||||
@@ -37,6 +41,9 @@ typedef struct ConnectionMapping {
|
||||
static const ConnectionMapping connectionMapping[] = {
|
||||
#ifdef HAVE_PCSTYLE_LPT_CONTROL
|
||||
{"t6963", GLCD_CT_T6963, glcd_t6963_init},
|
||||
#endif
|
||||
#ifdef HAVE_LIBPNG
|
||||
{"png", GLCD_CT_PNG, glcd_png_init},
|
||||
#endif
|
||||
/* default, end of structure element (do not delete) */
|
||||
{NULL, GLCD_CT_UNKNOWN, NULL}
|
||||
|
||||
@@ -14,8 +14,6 @@
|
||||
#define GLCD_MAX_WIDTH 640
|
||||
#define GLCD_MAX_HEIGHT 480
|
||||
|
||||
#define BYTES_PER_LINE (p->px_width / 8)
|
||||
|
||||
/** private data for the \c glcd driver */
|
||||
typedef struct glcd_private_data {
|
||||
unsigned char *framebuf; /**< frame buffer */
|
||||
@@ -27,6 +25,8 @@ typedef struct glcd_private_data {
|
||||
int height; /**< display height in characters */
|
||||
struct hwDependentFns *glcd_functions; /**< pointers to low-level functions */
|
||||
void *ct_data; /**< Connection type specific data */
|
||||
void *render_config; /**< Settings for the font renderer */
|
||||
char use_ft2; /**< (Not) use FreeType if available */
|
||||
} PrivateData;
|
||||
|
||||
/** Structure holding pointers to display specific functions */
|
||||
@@ -51,4 +51,37 @@ typedef struct hwDependentFns {
|
||||
void (*close)(PrivateData *p);
|
||||
} GLCD_functions;
|
||||
|
||||
/* ================== Framebuffer functions and macros =================== */
|
||||
|
||||
#define BYTES_PER_LINE (p->px_width / 8)
|
||||
#define FB_BYTES_TOTAL (p->px_height * BYTES_PER_LINE)
|
||||
|
||||
/**
|
||||
* Draw one pixel into the framebuffer using 1bpp (black and white). This
|
||||
* function actually decides about the format of the framebuffer. Using this
|
||||
* implementation (0,0) is top left and bytes contain pixels from left to right.
|
||||
*
|
||||
* \param p Pointer to driver's private data.
|
||||
* \param x X-position
|
||||
* \param y Y-position
|
||||
* \param color Pixel color: 1 = set (black), 0 = not set (blank/white)
|
||||
*/
|
||||
static inline void
|
||||
fb_draw_pixel(PrivateData *p, int x, int y, int color)
|
||||
{
|
||||
unsigned int pos; /* Byte within the framebuffer */
|
||||
unsigned char bit; /* Bit within the framebuffer byte */
|
||||
|
||||
if (x < 0 || x >= p->px_width || y < 0 || y >= p->px_height)
|
||||
return;
|
||||
|
||||
pos = y * BYTES_PER_LINE + (x / 8);
|
||||
bit = 0x80 >> (x % 8);
|
||||
|
||||
if (color == 1)
|
||||
p->framebuf[pos] |= bit;
|
||||
else
|
||||
p->framebuf[pos] &= ~bit;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
@@ -0,0 +1,171 @@
|
||||
/** \file server/drivers/glcd-png.c
|
||||
* This driver writes the framebuffer content to PNG images as
|
||||
* /tmp/lcdproc######.png.
|
||||
*/
|
||||
|
||||
/*-
|
||||
* Copyright (c) 2011 Markus Dolze
|
||||
*
|
||||
* This file is released under the GNU General Public License. Refer to the
|
||||
* COPYING file distributed with this package.
|
||||
*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <errno.h>
|
||||
#include <stdio.h>
|
||||
#include <sys/stat.h>
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <png.h>
|
||||
|
||||
#include "lcd.h"
|
||||
#include "report.h"
|
||||
#include "glcd-low.h"
|
||||
#include "glcd-png.h"
|
||||
|
||||
/** Private data for the PNG connection type */
|
||||
typedef struct glcd_png_data {
|
||||
unsigned char *backingstore; /**< backing buffer */
|
||||
} CT_png_data;
|
||||
|
||||
/**
|
||||
* API: Initialize the connection type driver.
|
||||
* \param drvthis Pointer to driver structure.
|
||||
* \retval 0 Success.
|
||||
* \retval <0 Error.
|
||||
*/
|
||||
int
|
||||
glcd_png_init(Driver *drvthis)
|
||||
{
|
||||
PrivateData *p = (PrivateData *)drvthis->private_data;
|
||||
CT_png_data *ct_data;
|
||||
|
||||
report(RPT_INFO, "GLCD/png: intializing");
|
||||
|
||||
/* Set up connection type low-level functions */
|
||||
p->glcd_functions->blit = glcd_png_blit;
|
||||
p->glcd_functions->close = glcd_png_close;
|
||||
|
||||
/* Allocate memory structures */
|
||||
ct_data = (CT_png_data *) calloc(1, sizeof(CT_png_data));
|
||||
if (ct_data == NULL) {
|
||||
report(RPT_ERR, "GLCD/png: error allocating connection data");
|
||||
return -1;
|
||||
}
|
||||
p->ct_data = ct_data;
|
||||
|
||||
ct_data->backingstore = malloc(FB_BYTES_TOTAL);
|
||||
if (ct_data->backingstore == NULL) {
|
||||
report(RPT_ERR, "GLCD/png: unable to allocate backing store");
|
||||
return -1;
|
||||
}
|
||||
memset(ct_data->backingstore, 0x00, FB_BYTES_TOTAL);
|
||||
|
||||
debug(RPT_DEBUG, "GLCD/png: init() done");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* API: Write the framebuffer to the display
|
||||
* \param p Pointer to glcd driver's private date structure.
|
||||
*/
|
||||
void
|
||||
glcd_png_blit(PrivateData *p)
|
||||
{
|
||||
CT_png_data *ct_data = (CT_png_data *) p->ct_data;
|
||||
char filename[256];
|
||||
static int num = 0;
|
||||
int row;
|
||||
FILE *fp;
|
||||
png_structp png_ptr;
|
||||
png_infop info_ptr;
|
||||
png_bytep row_pointer;
|
||||
|
||||
/* Check if framebufer has changed. If not there's nothing to do */
|
||||
if (memcmp(p->framebuf, ct_data->backingstore, FB_BYTES_TOTAL) == 0)
|
||||
return;
|
||||
|
||||
snprintf(filename, sizeof(filename), "/tmp/lcdproc%06d.png", num++);
|
||||
fp = fopen(filename, "wb");
|
||||
if (!fp) {
|
||||
p->glcd_functions->drv_debug(RPT_ERR, "File %s could not be opened for writing", filename);
|
||||
return;
|
||||
}
|
||||
|
||||
/* initialize stuff */
|
||||
png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
|
||||
if (!png_ptr) {
|
||||
p->glcd_functions->drv_debug(RPT_ERR, "png_create_write_struct failed");
|
||||
fclose(fp);
|
||||
return;
|
||||
}
|
||||
|
||||
info_ptr = png_create_info_struct(png_ptr);
|
||||
if (!info_ptr) {
|
||||
p->glcd_functions->drv_debug(RPT_ERR, "png_create_info_struct failed");
|
||||
png_destroy_write_struct(&png_ptr, (png_infopp) NULL);
|
||||
fclose(fp);
|
||||
return;
|
||||
}
|
||||
|
||||
if (setjmp(png_jmpbuf(png_ptr)))
|
||||
goto err_out;
|
||||
|
||||
png_init_io(png_ptr, fp);
|
||||
|
||||
png_set_IHDR(png_ptr, info_ptr, p->px_width, p->px_height,
|
||||
1, PNG_COLOR_TYPE_GRAY, PNG_INTERLACE_NONE,
|
||||
PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE);
|
||||
png_set_invert_mono(png_ptr);
|
||||
|
||||
png_write_info(png_ptr, info_ptr);
|
||||
|
||||
/* Write the image row by row */
|
||||
row_pointer = p->framebuf;
|
||||
for (row = 0; row < p->px_height; row++) {
|
||||
png_write_row(png_ptr, row_pointer);
|
||||
row_pointer += BYTES_PER_LINE;
|
||||
}
|
||||
|
||||
png_write_end(png_ptr, NULL);
|
||||
fclose(fp);
|
||||
fp = NULL;
|
||||
png_destroy_write_struct(&png_ptr, &info_ptr);
|
||||
|
||||
memcpy(ct_data->backingstore, p->framebuf, FB_BYTES_TOTAL);
|
||||
|
||||
return;
|
||||
|
||||
err_out:
|
||||
p->glcd_functions->drv_debug(RPT_ERR, "Error writing PNG image");
|
||||
if (fp != NULL)
|
||||
fclose(fp);
|
||||
if (png_ptr != NULL)
|
||||
png_destroy_write_struct(&png_ptr, &info_ptr);
|
||||
return;
|
||||
}
|
||||
|
||||
/**
|
||||
* API: Release low-level resources.
|
||||
* \param p Pointer to glcd driver's private date structure.
|
||||
*/
|
||||
void
|
||||
glcd_png_close(PrivateData *p)
|
||||
{
|
||||
if (p->ct_data != NULL) {
|
||||
CT_png_data *ct_data = (CT_png_data *) p->ct_data;
|
||||
|
||||
if (ct_data->backingstore != NULL)
|
||||
free(ct_data->backingstore);
|
||||
|
||||
free(p->ct_data);
|
||||
p->ct_data = NULL;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
#ifndef GLCD_PNG_H
|
||||
#define GLCD_PNG_H
|
||||
|
||||
int glcd_png_init(Driver *drvthis);
|
||||
void glcd_png_blit(PrivateData *p);
|
||||
void glcd_png_close(PrivateData *p);
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,348 @@
|
||||
/** \file server/drivers/glcd-render.c
|
||||
* Render glyphs to a framebuffer using FreeType2 or fixed 5x8 font.
|
||||
*/
|
||||
|
||||
/*-
|
||||
* Copyright (c) 2010 Bernhard Walle <bernhard@bwalle.de>
|
||||
* 2011 Markus Dolze <bsdfan@nurfuerspam.de>
|
||||
*
|
||||
* This file is released under the GNU General Public License. Refer to the
|
||||
* COPYING file distributed with this package.
|
||||
*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#ifdef HAVE_FT2
|
||||
#include <ft2build.h>
|
||||
#include FT_FREETYPE_H
|
||||
#endif
|
||||
|
||||
#include "lcd.h"
|
||||
#include "report.h"
|
||||
#include "glcd-low.h"
|
||||
#include "glcd-render.h"
|
||||
#include "glcd_font5x8.h"
|
||||
#include "shared/defines.h"
|
||||
|
||||
#ifdef HAVE_FT2
|
||||
/** Configuration for the Freetype renderer */
|
||||
typedef struct glcd_render_data {
|
||||
FT_Library ft_library; /**< freetype library handle */
|
||||
FT_Face ft_normal_font; /**< handle for the normal font */
|
||||
char ft_has_icons; /**< flag is the font has icons */
|
||||
} RenderConfig;
|
||||
|
||||
static int icon2unicode(int icon);
|
||||
#endif
|
||||
|
||||
|
||||
/**
|
||||
* Initializes rendering code. Any rendering related configuration settings
|
||||
* from LCDd.conf should be read here.
|
||||
*
|
||||
* \param drvthis Pointer to driver
|
||||
* \return 0 on success, -1 on error
|
||||
*
|
||||
* \note This function must be implemented, even if not compiled with Freetype!
|
||||
*/
|
||||
int
|
||||
glcd_render_init(Driver *drvthis)
|
||||
{
|
||||
#ifdef HAVE_FT2
|
||||
PrivateData *p = drvthis->private_data;
|
||||
int rc;
|
||||
const char *tmp;
|
||||
char font_file[255];
|
||||
RenderConfig *rconf;
|
||||
|
||||
debug(RPT_INFO, "%s(): Freetype", __FUNCTION__);
|
||||
|
||||
/* Allocate memory structures */
|
||||
rconf = (RenderConfig *) calloc(1, sizeof(RenderConfig));
|
||||
if (rconf == NULL) {
|
||||
report(RPT_ERR, "%s: error allocating rendering config", drvthis->name);
|
||||
return -1;
|
||||
}
|
||||
p->render_config = rconf;
|
||||
|
||||
/* use_ft2 is available in PrivateDate for easy use! */
|
||||
p->use_ft2 = drvthis->config_get_bool(drvthis->name, "useFT2", 0, 1);
|
||||
|
||||
/* Only configure FreeType if enabled */
|
||||
if (p->use_ft2) {
|
||||
/* get font from config file */
|
||||
tmp = drvthis->config_get_string(drvthis->name, "normal_font", 0, NULL);
|
||||
if (tmp == NULL) {
|
||||
report(RPT_ERR, "%s: normal_font missing in configuration", drvthis->name);
|
||||
goto err_out;
|
||||
}
|
||||
strncpy(font_file, tmp, sizeof(font_file));
|
||||
font_file[sizeof(font_file) - 1] = '\0';
|
||||
|
||||
/* initialize FreeType library */
|
||||
rc = FT_Init_FreeType(&rconf->ft_library);
|
||||
if (rc != 0) {
|
||||
report(RPT_ERR, "s: Freetype initialisation failed", drvthis->name);
|
||||
goto err_out;
|
||||
}
|
||||
|
||||
/* load the font face for freetype */
|
||||
rc = FT_New_Face(rconf->ft_library, font_file, 0, &rconf->ft_normal_font);
|
||||
if (rc != 0) {
|
||||
report(RPT_ERR, "s: Creation of font '%s' failed", drvthis->name, font_file);
|
||||
goto err_out;
|
||||
}
|
||||
|
||||
/* If the font does not have icons use default 5x8 font */
|
||||
rconf->ft_has_icons = drvthis->config_get_bool(drvthis->name, "fontHasIcons", 0, 1);
|
||||
}
|
||||
#endif
|
||||
|
||||
debug(RPT_INFO, "%s() successful", __FUNCTION__);
|
||||
return 0;
|
||||
|
||||
#ifdef HAVE_FT2
|
||||
err_out:
|
||||
glcd_render_close(drvthis);
|
||||
return -1;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Releases on resources used by the rendering code.
|
||||
*
|
||||
* \param drvthis Pointer to driver
|
||||
* \note This function must be implemented, even if not compiled with Freetype!
|
||||
*/
|
||||
void
|
||||
glcd_render_close(Driver *drvthis)
|
||||
{
|
||||
#ifdef HAVE_FT2
|
||||
PrivateData *p = drvthis->private_data;
|
||||
RenderConfig *rconf = p->render_config;
|
||||
|
||||
if (rconf != NULL) {
|
||||
if (rconf->ft_normal_font != NULL)
|
||||
FT_Done_Face(rconf->ft_normal_font);
|
||||
if (rconf->ft_library != NULL)
|
||||
FT_Done_FreeType(rconf->ft_library);
|
||||
|
||||
free(rconf);
|
||||
p->render_config = NULL;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
#ifdef HAVE_FT2
|
||||
/**
|
||||
* Draws character c to the framebuffer at position x,y using Freetype 2 for
|
||||
* font rendering. Top left corner is (1/1).
|
||||
*
|
||||
* \param drvthis Pointer to driver structure.
|
||||
* \param x Horizontal character position (column).
|
||||
* \param y Vertical character position (row).
|
||||
* \param c Character that gets written.
|
||||
*/
|
||||
void
|
||||
glcd_render_char_unicode(Driver *drvthis, int x, int y, int c)
|
||||
{
|
||||
static int last_font_size = -1;
|
||||
PrivateData *p = drvthis->private_data;
|
||||
RenderConfig *rconf = p->render_config;
|
||||
int font_size;
|
||||
int col, row; /* Position in the font bitmap */
|
||||
int px, py; /* Pixel position on the display */
|
||||
int rc;
|
||||
FT_Face face;
|
||||
FT_GlyphSlot glyph;
|
||||
FT_Bitmap *bitmap;
|
||||
unsigned char *bitmap_buf;
|
||||
|
||||
if (x < 1 || x > p->width || y < 1 || y > p->height)
|
||||
return;
|
||||
|
||||
x--; /* convert coordinates to zero-based */
|
||||
y--;
|
||||
|
||||
/* set the font size */
|
||||
font_size = max(p->cellheight, p->cellwidth);
|
||||
if (last_font_size != font_size) {
|
||||
rc = FT_Set_Pixel_Sizes(rconf->ft_normal_font, font_size, font_size);
|
||||
if (rc != 0) {
|
||||
report(RPT_ERR, "%s: Failed to set pixel size (%dx%x)", drvthis->name,
|
||||
p->cellwidth, p->cellheight);
|
||||
return;
|
||||
}
|
||||
|
||||
last_font_size = font_size;
|
||||
}
|
||||
|
||||
/* load the glyph and render it */
|
||||
rc = FT_Load_Char(rconf->ft_normal_font, c, FT_LOAD_RENDER | FT_LOAD_MONOCHROME);
|
||||
if (rc != 0) {
|
||||
report(RPT_ERR, "%s: loading char '%c' (0x%x) failed", drvthis->name, c, c);
|
||||
return;
|
||||
}
|
||||
|
||||
/* set some data elements for convenience */
|
||||
face = rconf->ft_normal_font;
|
||||
glyph = rconf->ft_normal_font->glyph;
|
||||
bitmap = &glyph->bitmap;
|
||||
bitmap_buf = bitmap->buffer;
|
||||
|
||||
py = y * p->cellheight;
|
||||
/* clear the cell */
|
||||
for (row = 0; row < p->cellheight; row++, py++) {
|
||||
px = x * p->cellwidth;
|
||||
for (col = 0; col < p->cellwidth; col++, px++) {
|
||||
fb_draw_pixel(p, px, py, 0);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Note: the font metrics may result in negative py value! So protect
|
||||
* it by restricting it to 0.
|
||||
*/
|
||||
py = max((y + 1) * p->cellheight + (face->size->metrics.descender >> 6) - glyph->bitmap_top, 0);
|
||||
/* and now copy the pixels */
|
||||
for (row = 0; (row < bitmap->rows) && (row < p->cellheight); row++) {
|
||||
px = x * p->cellwidth + glyph->bitmap_left;
|
||||
for (col = 0; col < bitmap->width; col++) {
|
||||
fb_draw_pixel(p, px, py, bitmap_buf[col / 8] >> (7 - (col % 8)) & 1);
|
||||
px++;
|
||||
}
|
||||
bitmap_buf += bitmap->pitch;
|
||||
py++;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Draws char c from our standard 5x8 font definition to the framebuffer at
|
||||
* position x,y. Top left corner is (1/1).
|
||||
*
|
||||
* \param drvthis Pointer to driver structure.
|
||||
* \param x Horizontal character position (column).
|
||||
* \param y Vertical character position (row).
|
||||
* \param c Character that gets written.
|
||||
*/
|
||||
void
|
||||
glcd_render_char(Driver *drvthis, int x, int y, unsigned char c)
|
||||
{
|
||||
PrivateData *p = drvthis->private_data;
|
||||
int font_x, font_y; /* Position in the font definition array */
|
||||
int px, py; /* Pixel position on the display */
|
||||
|
||||
if (x < 1 || x > p->width || y < 1 || y > p->height)
|
||||
return;
|
||||
|
||||
x--; /* convert coordinates to zero-based */
|
||||
y--;
|
||||
|
||||
/*
|
||||
* Algorithm: For each row in the font definition check if bit (dot)
|
||||
* at each column is set. If yes, plot a dot into the framebuffer. If
|
||||
* the bit is not set then clear the dot. Currently it is wrong to
|
||||
* assume the framebuffer is clear (e.g. the heartbeat does not clear
|
||||
* it's contents in advance).
|
||||
*/
|
||||
/* FIXME: What happens if font is larger than cell size? */
|
||||
py = y * p->cellheight;
|
||||
for (font_y = 0; font_y < GLCD_FONT_HEIGHT; font_y++) {
|
||||
px = x * p->cellwidth;
|
||||
/*
|
||||
* Note: Initializing font_x with font's width leaves one
|
||||
* empty column to the left.
|
||||
*/
|
||||
for (font_x = GLCD_FONT_WIDTH; font_x >= 0; font_x--) {
|
||||
if (glcd_iso8859_1[c][font_y] & (1 << font_x))
|
||||
fb_draw_pixel(p, px, py, 1);
|
||||
else
|
||||
fb_draw_pixel(p, px, py, 0);
|
||||
px++;
|
||||
}
|
||||
py++;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#ifdef HAVE_FT2
|
||||
/**
|
||||
* Maps a LCDproc icon to an Unicode codepoint for an icon.
|
||||
*
|
||||
* \param icon The LCDproc icon constant
|
||||
* \return Unicode value
|
||||
*/
|
||||
static int
|
||||
icon2unicode(int icon)
|
||||
{
|
||||
switch (icon) {
|
||||
case ICON_BLOCK_FILLED:
|
||||
return 0x2588; /* Full block */
|
||||
case ICON_HEART_FILLED:
|
||||
return 0x2665; /* Black heart suit */
|
||||
case ICON_HEART_OPEN:
|
||||
return 0x2661; /* White heart suit */
|
||||
case ICON_ARROW_UP:
|
||||
return 0x2191; /* Upwards arrow */
|
||||
case ICON_ARROW_DOWN:
|
||||
return 0x2193; /* Downwards arrow */
|
||||
case ICON_ARROW_LEFT:
|
||||
return 0x2190; /* Leftwards arrow */
|
||||
case ICON_ARROW_RIGHT:
|
||||
return 0x2192; /* Rightwards arrow */
|
||||
case ICON_CHECKBOX_OFF:
|
||||
return 0x2610; /* Ballot box */
|
||||
case ICON_CHECKBOX_ON:
|
||||
return 0x2611; /* Ballot box with check */
|
||||
case ICON_CHECKBOX_GRAY:
|
||||
return 0x2612; /* Ballot box with x */
|
||||
case ICON_ELLIPSIS:
|
||||
return 0x2026; /* Horizontal ellipsis */
|
||||
default:
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
/**
|
||||
* Place an icon on the screen using either our built-in standard font or
|
||||
* an Unicode icon rendered with Freetype.
|
||||
*
|
||||
* \param drvthis Pointer to driver structure.
|
||||
* \param x Horizontal character position (column).
|
||||
* \param y Vertical character position (row).
|
||||
* \param icon synbolic value representing the icon.
|
||||
* \retval 0 Icon has been successfully defined/written.
|
||||
* \retval <0 Server core shall define/write the icon.
|
||||
*/
|
||||
int
|
||||
glcd_render_icon(Driver *drvthis, int x, int y, int icon)
|
||||
{
|
||||
int icon_char;
|
||||
|
||||
#ifdef HAVE_FT2
|
||||
PrivateData *p = drvthis->private_data;
|
||||
RenderConfig *rconf = p->render_config;
|
||||
|
||||
if (p->use_ft2 && rconf->ft_has_icons) {
|
||||
if ((icon_char = icon2unicode(icon)) != -1) {
|
||||
glcd_render_char_unicode(drvthis, x, y, icon_char);
|
||||
return 0;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
#endif
|
||||
if ((icon_char = glcd_icon5x8(icon)) != -1) {
|
||||
glcd_render_char(drvthis, x, y, icon_char);
|
||||
return 0;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
#ifndef GLCD_RENDER_H
|
||||
#define GLCD_RENDER_H
|
||||
|
||||
int glcd_render_init(Driver *drvthis);
|
||||
void glcd_render_close(Driver *drvthis);
|
||||
void glcd_render_char(Driver *drvthis, int x, int y, unsigned char c);
|
||||
int glcd_render_icon(Driver *drvthis, int x, int y, int icon);
|
||||
|
||||
#ifdef HAVE_FT2
|
||||
void glcd_render_char_unicode(Driver *drvthis, int x, int y, int c);
|
||||
#endif
|
||||
|
||||
#endif
|
||||
@@ -67,7 +67,7 @@ glcd_t6963_init(Driver *drvthis)
|
||||
/* Allocate memory structures */
|
||||
ct_data = (CT_t6963_data *) calloc(1, sizeof(CT_t6963_data));
|
||||
if (ct_data == NULL) {
|
||||
report(RPT_ERR, "GLCD/T6963: error allocation connection data");
|
||||
report(RPT_ERR, "GLCD/T6963: error allocating connection data");
|
||||
return -1;
|
||||
}
|
||||
p->ct_data = ct_data;
|
||||
@@ -79,12 +79,12 @@ glcd_t6963_init(Driver *drvthis)
|
||||
}
|
||||
ct_data->port_config = port_config;
|
||||
|
||||
ct_data->backingstore = malloc(BYTES_PER_LINE * p->px_height);
|
||||
ct_data->backingstore = malloc(FB_BYTES_TOTAL);
|
||||
if (ct_data->backingstore == NULL) {
|
||||
report(RPT_ERR, "GLCD/T6963: unable to allocate backing store");
|
||||
return -1;
|
||||
}
|
||||
memset(ct_data->backingstore, 0x00, BYTES_PER_LINE * p->px_height);
|
||||
memset(ct_data->backingstore, 0x00, FB_BYTES_TOTAL);
|
||||
|
||||
/* Get port from config */
|
||||
port_config->port = drvthis->config_get_int(drvthis->name, "Port", 0, DEFAULT_PORT);
|
||||
@@ -189,6 +189,7 @@ glcd_t6963_close(PrivateData *p)
|
||||
free(ct_data->backingstore);
|
||||
|
||||
free(p->ct_data);
|
||||
p->ct_data = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -201,7 +202,7 @@ static void
|
||||
t6963_graphic_clear(PrivateData *p)
|
||||
{
|
||||
CT_t6963_data *ct_data = (CT_t6963_data *) p->ct_data;
|
||||
int num = BYTES_PER_LINE * p->px_height;
|
||||
int num = FB_BYTES_TOTAL;
|
||||
int i;
|
||||
|
||||
p->glcd_functions->drv_debug(RPT_DEBUG, "GLCD/T6963: Clearing graphic: %d bytes", num);
|
||||
|
||||
+62
-124
@@ -25,25 +25,15 @@
|
||||
* \li glcd-drivers.h CT-driver registry. Add a pointer to your CT-driver's
|
||||
* init() function here.
|
||||
* \li glcd-low.h Base driver's PrivateData and ConnectionType API.
|
||||
* \li glcd-render.c Render characters using FreeType 2 or standard font.
|
||||
* \li glcd_font5x8.h LCDproc's default fixed 5x8 font.
|
||||
*/
|
||||
|
||||
/*-
|
||||
* Copyright (C) 2011, Markus Dolze
|
||||
*
|
||||
* 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 of the License, or
|
||||
* 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301
|
||||
* This file is released under the GNU General Public License. Refer to the
|
||||
* COPYING file distributed with this package.
|
||||
*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
@@ -60,7 +50,7 @@
|
||||
#include "glcd-low.h"
|
||||
#include "glcd-drivers.h"
|
||||
#include "report.h"
|
||||
#include "glcd_font5x8.h"
|
||||
#include "glcd-render.h"
|
||||
|
||||
/* Vars for the server core */
|
||||
MODULE_EXPORT char *api_version = API_VERSION;
|
||||
@@ -68,9 +58,6 @@ MODULE_EXPORT int stay_in_foreground = 0;
|
||||
MODULE_EXPORT int supports_multiple = 0;
|
||||
MODULE_EXPORT char *symbol_prefix = "glcd_";
|
||||
|
||||
static void glcd_render_char(Driver *drvthis, int x, int y, unsigned char c);
|
||||
static inline void glcd_draw_pixel(PrivateData *p, int x, int y, int color);
|
||||
|
||||
/**
|
||||
* Initialize the driver. (Required)
|
||||
* \param drvthis Pointer to driver structure.
|
||||
@@ -162,12 +149,16 @@ glcd_init(Driver *drvthis)
|
||||
p->height = p->px_height / p->cellheight;
|
||||
|
||||
/* Allocate framebuffer */
|
||||
p->framebuf = malloc(BYTES_PER_LINE * p->px_height);
|
||||
p->framebuf = malloc(FB_BYTES_TOTAL);
|
||||
if (p->framebuf == NULL) {
|
||||
report(RPT_ERR, "%s: unable to allocate framebuffer", drvthis->name);
|
||||
return -1;
|
||||
}
|
||||
memset(p->framebuf, 0x00, BYTES_PER_LINE * p->px_height);
|
||||
memset(p->framebuf, 0x00, FB_BYTES_TOTAL);
|
||||
|
||||
/* Initialize renderer */
|
||||
if (glcd_render_init(drvthis) != 0)
|
||||
return -1;
|
||||
|
||||
glcd_clear(drvthis);
|
||||
|
||||
@@ -192,6 +183,7 @@ glcd_close(Driver *drvthis)
|
||||
if (p->framebuf != NULL)
|
||||
free(p->framebuf);
|
||||
p->framebuf = NULL;
|
||||
glcd_render_close(drvthis);
|
||||
|
||||
free(p);
|
||||
}
|
||||
@@ -274,7 +266,7 @@ glcd_clear(Driver *drvthis)
|
||||
|
||||
debug(RPT_DEBUG, "%s()", __FUNCTION__);
|
||||
|
||||
memset(p->framebuf, 0x00, BYTES_PER_LINE * p->px_height);
|
||||
memset(p->framebuf, 0x00, FB_BYTES_TOTAL);
|
||||
|
||||
}
|
||||
|
||||
@@ -313,14 +305,17 @@ glcd_string(Driver *drvthis, int x, int y, const char string[])
|
||||
|
||||
debug(RPT_DEBUG, "%s(%i,%i,%.40s)", __FUNCTION__, x, y, string);
|
||||
|
||||
y--; /* Convert 1-based coords to 0-based... */
|
||||
x--;
|
||||
|
||||
if ((y < 0) || (y >= p->height))
|
||||
if ((y < 1) || (y > p->height))
|
||||
return;
|
||||
|
||||
for (i = 0; (string[i] != '\0') && (x < p->width); i++, x++)
|
||||
glcd_render_char(drvthis, x, y, string[i]);
|
||||
for (i = 0; (string[i] != '\0') && (x <= p->width); i++, x++) {
|
||||
#ifdef HAVE_FT2
|
||||
if (p->use_ft2)
|
||||
glcd_render_char_unicode(drvthis, x, y, string[i] & 0xFF);
|
||||
else
|
||||
#endif
|
||||
glcd_render_char(drvthis, x, y, string[i]);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -341,66 +336,81 @@ glcd_string(Driver *drvthis, int x, int y, const char string[])
|
||||
MODULE_EXPORT void
|
||||
glcd_chr(Driver *drvthis, int x, int y, char c)
|
||||
{
|
||||
#ifdef HAVE_FT2
|
||||
PrivateData *p = drvthis->private_data;
|
||||
#endif
|
||||
debug(RPT_DEBUG, "%s(%i,%i,%c)", __FUNCTION__, x, y, c);
|
||||
|
||||
x--;
|
||||
y--;
|
||||
glcd_render_char(drvthis, x, y, c);
|
||||
#ifdef HAVE_FT2
|
||||
if (p->use_ft2)
|
||||
glcd_render_char_unicode(drvthis, x, y, c & 0xFF);
|
||||
else
|
||||
#endif
|
||||
glcd_render_char(drvthis, x, y, c);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Place an icon on the screen. (Optional)
|
||||
* \param drvthis Pointer to driver structure.
|
||||
* \param x Horizontal character position (column).
|
||||
* \param y Vertical character position (row).
|
||||
* \param icon synbolic value representing the icon.
|
||||
* \retval 0 Icon has been successfully defined/written.
|
||||
* \retval <0 Server core shall define/write the icon.
|
||||
* API: Place an icon on the screen.
|
||||
*/
|
||||
MODULE_EXPORT int
|
||||
glcd_icon(Driver *drvthis, int x, int y, int icon)
|
||||
{
|
||||
debug(RPT_DEBUG, "%s(%i,%i,%i)", __FUNCTION__, x, y, icon);
|
||||
|
||||
return (glcd_icon5x8(drvthis, x, y, icon));
|
||||
return (glcd_render_icon(drvthis, x, y, icon));
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* API: Draws a vertical bar, from the bottom of the screen up.
|
||||
*/
|
||||
MODULE_EXPORT void
|
||||
glcd_vbar(Driver *drvthis, int x, int y, int len, int promille, int options)
|
||||
{
|
||||
PrivateData *p = drvthis->private_data;
|
||||
int xstart, xend, ystart, yend;
|
||||
int col, row;
|
||||
|
||||
debug(RPT_DEBUG, "%s(%i,%i,%i,%i,%i)", __FUNCTION__, x, y, len, promille, options);
|
||||
lib_vbar_static(drvthis, x, y, len, promille, options, GLCD_FONT_HEIGHT, 0x90);
|
||||
|
||||
/* leave first column and top row empty */
|
||||
xstart = (x - 1) * p->cellwidth + 1;
|
||||
xend = xstart + p->cellwidth - 1;
|
||||
ystart = y * p->cellheight;
|
||||
yend = ystart - (((long) 2 * len * p->cellheight) * promille / 2000) + 1;
|
||||
|
||||
for (col = xstart; col < xend; col++) {
|
||||
for (row = ystart; row > yend; row--) {
|
||||
fb_draw_pixel(p, col, row, 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* API: Draws a horizontal bar to the right.
|
||||
*
|
||||
* \note For hBars the actual width of the font (5) has to be used instead
|
||||
* of the cell width (6)!
|
||||
*/
|
||||
MODULE_EXPORT void
|
||||
glcd_hbar(Driver *drvthis, int x, int y, int len, int promille, int options)
|
||||
{
|
||||
int pixels = ((long) 2 * len * GLCD_FONT_WIDTH) * promille / 2000;
|
||||
int pos;
|
||||
PrivateData *p = drvthis->private_data;
|
||||
int xstart, xend, ystart, yend;
|
||||
int col, row;
|
||||
|
||||
debug(RPT_DEBUG, "%s(%i,%i,%i,%i,%i)", __FUNCTION__, x, y, len, promille, options);
|
||||
|
||||
for (pos = 0; pos < len; pos++) {
|
||||
if (pixels >= GLCD_FONT_WIDTH )
|
||||
glcd_chr(drvthis, x + pos, y, 0x9e);
|
||||
else if (pixels >= 1)
|
||||
glcd_chr(drvthis, x + pos, y, 0x99 + pixels);
|
||||
else
|
||||
; /* do nothing */
|
||||
pixels -= GLCD_FONT_WIDTH;
|
||||
/* leave first column and top row empty */
|
||||
xstart = (x - 1) * p->cellwidth + 1;
|
||||
xend = xstart + (((long) 2 * len * p->cellwidth) * promille / 2000) - 1;
|
||||
ystart = (y - 1) * p->cellheight + 1;
|
||||
yend = ystart + p->cellheight - 1;
|
||||
|
||||
for (row = ystart; row < yend; row++) {
|
||||
for (col = xstart; col < xend; col++) {
|
||||
fb_draw_pixel(p, col, row, 1);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -418,75 +428,3 @@ glcd_get_info(Driver *drvthis)
|
||||
|
||||
return info_string;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Draw one pixel into the framebuffer using 1bpp (black and white). This
|
||||
* function actually decides about the format of the framebuffer. Using this
|
||||
* implementation (0,0) is top left and bytes contain pixels from left to right.
|
||||
*
|
||||
* \param p Pointer to driver's private data.
|
||||
* \param x X-position
|
||||
* \param y Y-position
|
||||
* \param color Pixel color: 1 = set (black), 0 = not set (blank)
|
||||
*/
|
||||
static inline void
|
||||
glcd_draw_pixel(PrivateData *p, int x, int y, int color)
|
||||
{
|
||||
unsigned int pos; /* Byte within the framebuffer */
|
||||
unsigned char bit; /* Bit within the framebuffer byte */
|
||||
|
||||
pos = y * BYTES_PER_LINE + (x / 8);
|
||||
bit = 0x80 >> (x % 8);
|
||||
|
||||
if (color == 1)
|
||||
p->framebuf[pos] |= bit;
|
||||
else
|
||||
p->framebuf[pos] &= ~bit;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Draws char c from font definition to the framebuffer at position
|
||||
* x,y. These are zero-based textmode positions.
|
||||
*
|
||||
* \param drvthis Pointer to driver structure.
|
||||
* \param x Horizontal character position (column).
|
||||
* \param y Vertical character position (row).
|
||||
* \param c Character that gets written.
|
||||
*/
|
||||
static void
|
||||
glcd_render_char(Driver *drvthis, int x, int y, unsigned char c)
|
||||
{
|
||||
PrivateData *p = drvthis->private_data;
|
||||
int font_x, font_y; /* Position in the font definition array */
|
||||
int px, py; /* Pixel position on the display */
|
||||
|
||||
if (x < 0 || x >= p->width || y < 0 || y >= p->height)
|
||||
return;
|
||||
|
||||
/*
|
||||
* Algorithm: For each row in the font definition check if bit (dot)
|
||||
* at each column is set. If yes, plot a dot into the framebuffer. If
|
||||
* the bit is not set then clear the dot. Currently it is wrong to
|
||||
* assume the framebuffer is clear (e.g. the heartbeat does not clear
|
||||
* it's contents in advance).
|
||||
*/
|
||||
/* FIXME: What happens if font is larger than cell size? */
|
||||
py = y * p->cellheight;
|
||||
for (font_y = 0; (font_y < GLCD_FONT_HEIGHT) && (py < p->px_height); font_y++) {
|
||||
px = x * p->cellwidth;
|
||||
/*
|
||||
* Note: Initializing font_x with font's width leaves one
|
||||
* empty column to the left.
|
||||
*/
|
||||
for (font_x = GLCD_FONT_WIDTH; (font_x > -1) && (px < p->px_width); font_x--) {
|
||||
if (glcd_iso8859_1[c][font_y] & (1 << font_x))
|
||||
glcd_draw_pixel(p, px, py, 1);
|
||||
else
|
||||
glcd_draw_pixel(p, px, py, 0);
|
||||
px++;
|
||||
}
|
||||
py++;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user