/* $Id$ * $URL$ * * 6x8 font * * Copyright (C) 1999, 2000, 2004 Michael Reinelt * Copyright (C) 2004 The LCD4Linux Team * * 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. * */ #define ______ 0x00 #define _____O 0x01 #define ____O_ 0x02 #define ____OO 0x03 #define ___O__ 0x04 #define ___O_O 0x05 #define ___OO_ 0x06 #define ___OOO 0x07 #define __O___ 0x08 #define __O__O 0x09 #define __O_O_ 0x0a #define __O_OO 0x0b #define __OO__ 0x0c #define __OO_O 0x0d #define __OOO_ 0x0e #define __OOOO 0x0f #define _O____ 0x10 #define _O___O 0x11 #define _O__O_ 0x12 #define _O__OO 0x13 #define _O_O__ 0x14 #define _O_O_O 0x15 #define _O_OO_ 0x16 #define _O_OOO 0x17 #define _OO___ 0x18 #define _OO__O 0x19 #define _OO_O_ 0x1a #define _OO_OO 0x1b #define _OOO__ 0x1c #define _OOO_O 0x1d #define _OOOO_ 0x1e #define _OOOOO 0x1f unsigned char Font_6x8[256][8] = { [0x20] {______, ______, ______, ______, ______, ______, ______, ______}, [0x21] {___O__, ___O__, ___O__, ___O__, ______, ______, ___O__, ______}, [0x22] {__O_O_, __O_O_, __O_O_, ______, ______, ______, ______, ______}, [0x23] {__O_O_, __O_O_, _OOOOO, __O_O_, _OOOOO, __O_O_, __O_O_, ______}, [0x24] {___O__, __OOOO, _O_O__, __OOO_, ___O_O, _OOOO_, ___O__, ______}, [0x25] {_OO___, _OO__O, ____O_, ___O__, __O___, _O__OO, ____OO, ______}, [0x26] {__OO__, _O__O_, _O_O__, __O___, _O_O_O, _O__O_, __OO_O, ______}, [0x27] {__OO__, ___O__, __O___, ______, ______, ______, ______, ______}, [0x28] {____O_, ___O__, __O___, __O___, __O___, ___O__, ____O_, ______}, [0x29] {__O___, ___O__, ____O_, ____O_, ____O_, ___O__, __O___, ______}, [0x2a] {______, ___O__, _O_O_O, __OOO_, _O_O_O, ___O__, ______, ______}, [0x2b] {______, ___O__, ___O__, _OOOOO, ___O__, ___O__, ______, ______}, [0x2c] {______, ______, ______, ______, __OO__, ___O__, __O___, ______}, [0x2d] {______, ______, ______, _OOOOO, ______, ______, ______, ______}, [0x2e] {______, ______, ______, ______, ______, __OO__, __OO__, ______}, [0x2f] {______, _____O, ____O_, ___O__, __O___, _O____, ______, ______}, [0x30] {__OOO_, _O___O, _O__OO, _O_O_O, _OO__O, _O___O, __OOO_, ______}, [0x31] {___O__, __OO__, ___O__, ___O__, ___O__, ___O__, __OOO_, ______}, [0x32] {__OOO_, _O___O, _____O, ____O_, ___O__, __O___, _OOOOO, ______}, [0x33] {_OOOOO, ____O_, ___O__, ____O_, _____O, _O___O, __OOO_, ______}, [0x34] {____O_, ___OO_, __O_O_, _O__O_, _OOOOO, ____O_, ____O_, ______}, [0x35] {_OOOOO, _O____, _O____, _OOOO_, _____O, _O___O, __OOO_, ______}, [0x36] {___OO_, __O___, _O____, _OOOO_, _O___O, _O___O, __OOO_, ______}, [0x37] {_OOOOO, _____O, ____O_, ___O__, __O___, __O___, __O___, ______}, [0x38] {__OOO_, _O___O, _O___O, __OOO_, _O___O, _O___O, __OOO_, ______}, [0x39] {__OOO_, _O___O, _O___O, __OOOO, _____O, ____O_, __OO__, ______}, [0x3a] {______, __OO__, __OO__, ______, __OO__, __OO__, ______, ______}, [0x3b] {______, __OO__, __OO__, ______, __OO__, ___O__, __O___, ______}, [0x3c] {____O_, ___O__, __O___, _O____, __O___, ___O__, ____O_, ______}, [0x3d] {______, ______, _OOOOO, ______, _OOOOO, ______, ______, ______}, [0x3e] {_O____, __O___, ___O__, ____O_, ___O__, __O___, _O____, ______}, [0x3f] {__OOO_, _O___O, _____O, ____O_, ___O__, ______, ___O__, ______}, [0x40] {__OOO_, _O___O, _____O, __OO_O, _O_O_O, _O_O_O, __OOO_, ______}, [0x41] {__OOO_, _O___O, _O___O, _O___O, _OOOOO, _O___O, _O___O, ______}, [0x42] {_OOOO_, _O___O, _O___O, _OOOO_, _O___O, _O___O, _OOOO_, ______}, [0x43] {__OOO_, _O___O, _O____, _O____, _O____, _O___O, __OOO_, ______}, [0x44] {_OOO__, _O__O_, _O___O, _O___O, _O___O, _O__O_, _OOO__, ______}, [0x45] {_OOOOO, _O____, _O____, _OOOO_, _O____, _O____, _OOOOO, ______}, [0x46] {_OOOOO, _O____, _O____, _OOOO_, _O____, _O____, _O____, ______}, [0x47] {__OOO_, _O___O, _O____, _O_OOO, _O___O, _O___O, __OOOO, ______}, [0x48] {_O___O, _O___O, _O___O, _OOOOO, _O___O, _O___O, _O___O, ______}, [0x49] {__OOO_, ___O__, ___O__, ___O__, ___O__, ___O__, __OOO_, ______}, [0x4a] {___OOO, ____O_, ____O_, ____O_, ____O_, _O__O_, __OO__, ______}, [0x4b] {_O___O, _O__O_, _O_O__, _OO___, _O_O__, _O__O_, _O___O, ______}, [0x4c] {_O____, _O____, _O____, _O____, _O____, _O____, _OOOOO, ______}, [0x4d] {_O___O, _OO_OO, _O_O_O, _O_O_O, _O___O, _O___O, _O___O, ______}, [0x4e] {_O___O, _O___O, _OO__O, _O_O_O, _O__OO, _O___O, _O___O, ______}, [0x4f] {__OOO_, _O___O, _O___O, _O___O, _O___O, _O___O, __OOO_, ______}, [0x50] {_OOOO_, _O___O, _O___O, _OOOO_, _O____, _O____, _O____, ______}, [0x51] {__OOO_, _O___O, _O___O, _O___O, _O_O_O, _O__O_, __OO_O, ______}, [0x52] {_OOOO_, _O___O, _O___O, _OOOO_, _O_O__, _O__O_, _O___O, ______}, [0x53] {__OOOO, _O____, _O____, __OOO_, _____O, _____O, _OOOO_, ______}, [0x54] {_OOOOO, ___O__, ___O__, ___O__, ___O__, ___O__, ___O__, ______}, [0x55] {_O___O, _O___O, _O___O, _O___O, _O___O, _O___O, __OOO_, ______}, [0x56] {_O___O, _O___O, _O___O, _O___O, _O___O, __O_O_, ___O__, ______}, [0x57] {_O___O, _O___O, _O___O, _O_O_O, _O_O_O, _O_O_O, __O_O_, ______}, [0x58] {_O___O, _O___O, __O_O_, ___O__, __O_O_, _O___O, _O___O, ______}, [0x59] {_O___O, _O___O, _O___O, __O_O_, ___O__, ___O__, ___O__, ______}, [0x5a] {_OOOOO, _____O, ____O_, ___O__, __O___, _O____, _OOOOO, ______}, [0x5b] {__OOO_, __O___, __O___, __O___, __O___, __O___, __OOO_, ______}, [0x5c] {_O___O, __O_O_, _OOOOO, ___O__, _OOOOO, ___O__, ___O__, ______}, [0x5d] {__OOO_, ____O_, ____O_, ____O_, ____O_, ____O_, __OOO_, ______}, [0x5e] {___O__, __O_O_, _O___O, ______, ______, ______, ______, ______}, [0x5f] {______, ______, ______, ______, ______, ______, _OOOOO, ______}, [0x60] {__O___, ___O__, ____O_, ______, ______, ______, ______, ______}, [0x61] {______, ______, __OOO_, _____O, __OOOO, _O___O, __OOOO, ______}, [0x62] {_O____, _O____, _O_OO_, _OO__O, _O___O, _O___O, _OOOO_, ______}, [0x63] {______, ______, __OOO_, _O____, _O____, _O___O, __OOO_, ______}, [0x64] {_____O, _____O, __OO_O, _O__OO, _O___O, _O___O, __OOOO, ______}, [0x65] {______, ______, __OOO_, _O___O, _OOOOO, _O____, __OOO_, ______}, [0x66] {___OO_, __O__O, __O___, _OOO__, __O___, __O___, __O___, ______}, [0x67] {______, ______, __OOOO, _O___O, _O___O, __OOOO, _____O, __OOO_}, [0x68] {_O____, _O____, _O_OO_, _OO__O, _O___O, _O___O, _O___O, ______}, [0x69] {___O__, ______, __OO__, ___O__, ___O__, ___O__, __OOO_, ______}, [0x6a] {____O_, ______, ___OO_, ____O_, ____O_, _O__O_, __OO__, ______}, [0x6b] {__O___, __O___, __O__O, __O_O_, __OO__, __O_O_, __O__O, ______}, [0x6c] {__OO__, ___O__, ___O__, ___O__, ___O__, ___O__, __OOO_, ______}, [0x6d] {______, ______, _OO_O_, _O_O_O, _O_O_O, _O___O, _O___O, ______}, [0x6e] {______, ______, _OOOO_, _O___O, _O___O, _O___O, _O___O, ______}, [0x6f] {______, ______, __OOO_, _O___O, _O___O, _O___O, __OOO_, ______}, [0x70] {______, ______, _OOOO_, _O___O, _O___O, _OOOO_, _O____, _O____}, [0x71] {______, ______, __OO_O, _O__OO, _O___O, __OOOO, _____O, _____O}, [0x72] {______, ______, _O_OO_, _OO__O, _O____, _O____, _O____, ______}, [0x73] {______, ______, __OOO_, _O____, __OOO_, _____O, _OOOO_, ______}, [0x74] {__O___, __O___, _OOO__, __O___, __O___, __O__O, ___OO_, ______}, [0x75] {______, ______, _O___O, _O___O, _O___O, _O__OO, __OO_O, ______}, [0x76] {______, ______, _O___O, _O___O, _O___O, __O_O_, ___O__, ______}, [0x77] {______, ______, _O___O, _O___O, _O___O, _O_O_O, __O_O_, ______}, [0x78] {______, ______, _O___O, __O_O_, ___O__, __O_O_, _O___O, ______}, [0x79] {______, ______, _O___O, _O___O, __OOOO, _____O, __OOO_, ______}, [0x7a] {______, ______, _OOOOO, ____O_, ___O__, __O___, _OOOOO, ______}, [0x7b] {____O_, ___O__, ___O__, __O___, ___O__, ___O__, ____O_, ______}, [0x7c] {___O__, ___O__, ___O__, ___O__, ___O__, ___O__, ___O__, ______}, [0x7d] {__O___, ___O__, ___O__, ____O_, ___O__, ___O__, __O___, ______}, [0x7e] {______, ___O__, ____O_, _OOOOO, ____O_, ___O__, ______, ______}, [0x7f] {______, ___O__, __O___, _OOOOO, __O___, ___O__, ______, ______}, [0xb0] {__OOO_, __O_O_, __OOO_, ______, ______, ______, ______, ______}, [0xe1] {__O_O_, ______, __OOO_, _____O, __OOOO, _O___O, __OOOO, ______}, [0xe2] {__OOO_, _O___O, _OOOO_, _O___O, _O___O, _O_OO_, _O____, ______}, [0xef] {__O_O_, ______, __OOO_, _O___O, _O___O, _O___O, __OOO_, ______}, [0xf5] {__O_O_, ______, _O___O, _O___O, _O___O, _O__OO, __OO_O, ______}, }; ' href='#n308'>308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339
/* $Id: widget_image.c,v 1.9 2006/06/21 05:12:43 reinelt Exp $
 *
 * image widget handling
 *
 * Copyright (C) 2006 Michael Reinelt <reinelt@eunet.at>
 * Copyright (C) 2006 The LCD4Linux Team <lcd4linux-devel@users.sourceforge.net>
 *
 * 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.
 *
 *
 * $Log: widget_image.c,v $
 * Revision 1.9  2006/06/21 05:12:43  reinelt
 * added checks for libgd version 2 (thanks to Sam)
 *
 * Revision 1.8  2006/06/20 08:50:59  reinelt
 * widget_image linker error hopefully finally fixed
 *
 * Revision 1.7  2006/04/15 05:22:52  reinelt
 * mpd plugin from Stefan Kuhne
 *
 * Revision 1.6  2006/04/09 14:17:50  reinelt
 * autoconf/library fixes, image and graphic display inversion
 *
 * Revision 1.5  2006/02/25 13:36:33  geronet
 * updated indent.sh, applied coding style
 *
 * Revision 1.4  2006/02/19 07:20:54  reinelt
 * image support nearly finished
 *
 * Revision 1.3  2006/02/08 04:55:05  reinelt
 * moved widget registration to drv_generic_graphic
 *
 * Revision 1.2  2006/01/23 06:17:18  reinelt
 * timer widget added
 *
 * Revision 1.1  2006/01/22 09:16:11  reinelt
 * Image Widget framework added
 *
 */

/* 
 * exported functions:
 *
 * WIDGET_CLASS Widget_Image
 *   the image widget
 *
 */


#include "config.h"

#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <ctype.h>
#include <errno.h>

#include "debug.h"
#include "cfg.h"
#include "qprintf.h"
#include "evaluator.h"
#include "timer.h"
#include "widget.h"
#include "widget_image.h"
#include "rgb.h"

#ifdef HAVE_GD_GD_H
#include <gd/gd.h>
#else
#ifdef HAVE_GD_H
#include <gd.h>
#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

#ifdef WITH_DMALLOC
#include <dmalloc.h>
#endif


static void widget_image_render(const char *Name, WIDGET_IMAGE * Image)
{
    int x, y;
    FILE *fd;
    gdImagePtr gdImage = NULL;

    /* 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;
	}
    }

    if (Image->file == NULL || Image->file[0] == '\0') {
	error("Warning: Image %s has no file", Name);
	return;
    }

    fd = fopen(Image->file, "rb");
    if (fd == NULL) {
	error("Warning: Image %s: fopen(%s) failed: %s", Name, Image->file, strerror(errno));
	return;
    }

    gdImage = gdImageCreateFromPng(fd);
    fclose(fd);

    if (fd == NULL) {
	error("Warning: Image %s: CreateFromPng(%s) failed!", Name, Image->file);
	return;
    }

    /* maybe resize bitmap */
    if (gdImage->sx > Image->width) {
	Image->width = gdImage->sx;
	if (Image->bitmap)
	    free(Image->bitmap);
	Image->bitmap = NULL;
    }
    if (gdImage->sy > Image->height) {
	Image->height = gdImage->sy;
	if (Image->bitmap)
	    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!", 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 */
    if (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 (Image->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_image_update(void *Self)
{
    WIDGET *W = (WIDGET *) Self;
    WIDGET_IMAGE *Image = W->data;
    RESULT result = { 0, 0, 0, NULL };

    /* process the parent only */
    if (W->parent == NULL) {

	/* evaluate expressions */
	if (Image->file) {
	    free(Image->file);
	    Image->file = NULL;
	}
	if (Image->file_tree != NULL) {
	    Eval(Image->file_tree, &result);
	    Image->file = strdup(R2S(&result));
	    DelResult(&result);
	}

	Image->update = 0;
	if (Image->update_tree != NULL) {
	    Eval(Image->update_tree, &result);
	    Image->update = R2N(&result);
	    if (Image->update < 0)
		Image->update = 0;
	    DelResult(&result);
	}

	Image->visible = 1;
	if (Image->visible_tree != NULL) {
	    Eval(Image->visible_tree, &result);
	    Image->visible = R2N(&result);
	    Image->visible = Image->visible > 0;
	    DelResult(&result);
	}

	Image->inverted = 0;
	if (Image->inverted_tree != NULL) {
	    Eval(Image->inverted_tree, &result);
	    Image->inverted = R2N(&result);
	    Image->inverted = Image->inverted > 0;
	    DelResult(&result);
	}

	/* render image into bitmap */
	widget_image_render(W->name, Image);

    }

    /* finally, draw it! */
    if (W->class->draw)
	W->class->draw(W);

    /* add a new one-shot timer */
    timer_add(widget_image_update, Self, Image->update, 1);

}



int widget_image_init(WIDGET * Self)
{
    char *section;
    WIDGET_IMAGE *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_IMAGE));
	memset(Image, 0, sizeof(WIDGET_IMAGE));

	/* initial size */
	Image->width = 0;
	Image->height = 0;
	Image->bitmap = NULL;
	Image->file = NULL;

	/* get raw expressions (we evaluate them ourselves) */
	Image->file_expr = cfg_get_raw(section, "file", NULL);
	Image->update_expr = cfg_get_raw(section, "update", NULL);
	Image->visible_expr = cfg_get_raw(section, "visible", NULL);
	Image->inverted_expr = cfg_get_raw(section, "inverted", NULL);

	/* sanity checks */
	if (Image->file_expr == NULL || *Image->file_expr == '\0') {
	    error("Warning: Image %s has no file", Self->name);
	}
	if (Image->update_expr == NULL || *Image->update_expr == '\0') {
	    error("Image %s has no update, using '100'", Self->name);
	    Image->update_expr = "100";
	}

	/* compile'em */
	Compile(Image->file_expr, &Image->file_tree);
	Compile(Image->update_expr, &Image->update_tree);
	Compile(Image->visible_expr, &Image->visible_tree);
	Compile(Image->inverted_expr, &Image->inverted_tree);

	free(section);
	Self->data = Image;

    } else {

	/* re-use the parent */
	Self->data = Self->parent->data;

    }

    /* just do it! */
    widget_image_update(Self);

    return 0;
}


int widget_image_quit(WIDGET * Self)
{
    if (Self) {
	/* do not deallocate child widget! */
	if (Self->parent == NULL) {
	    if (Self->data) {
		WIDGET_IMAGE *Image = Self->data;
		if (Image->bitmap)
		    free(Image->bitmap);
		if (Image->file)
		    free(Image->file);
		DelTree(Image->file_tree);
		DelTree(Image->update_tree);
		DelTree(Image->visible_tree);
		DelTree(Image->inverted_tree);
		free(Self->data);
		Self->data = NULL;
	    }
	}
    }

    return 0;

}



WIDGET_CLASS Widget_Image = {
  name:"image",
  type:WIDGET_TYPE_XY,
  init:widget_image_init,
  draw:NULL,
  quit:widget_image_quit,
};