~siretart/lcd4linux/debian

« back to all changes in this revision

Viewing changes to drv_generic_graphic.c

  • Committer: Reinhard Tartler
  • Date: 2011-04-27 17:24:15 UTC
  • mto: This revision was merged to the branch mainline in revision 750.
  • Revision ID: siretart@tauware.de-20110427172415-6n4aptmvmz0eztvm
Tags: upstream-0.11.0~svn1143
ImportĀ upstreamĀ versionĀ 0.11.0~svn1143

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* $Id: drv_generic_graphic.c 1003 2009-03-26 08:11:33Z michux $
 
2
 * $URL: https://ssl.bulix.org/svn/lcd4linux/trunk/drv_generic_graphic.c $
 
3
 *
 
4
 * generic driver helper for graphic displays
 
5
 *
 
6
 * Copyright (C) 1999, 2000 Michael Reinelt <michael@reinelt.co.at>
 
7
 * Copyright (C) 2004 The LCD4Linux Team <lcd4linux-devel@users.sourceforge.net>
 
8
 *
 
9
 * This file is part of LCD4Linux.
 
10
 *
 
11
 * LCD4Linux is free software; you can redistribute it and/or modify
 
12
 * it under the terms of the GNU General Public License as published by
 
13
 * the Free Software Foundation; either version 2, or (at your option)
 
14
 * any later version.
 
15
 *
 
16
 * LCD4Linux is distributed in the hope that it will be useful,
 
17
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 
18
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
19
 * GNU General Public License for more details.
 
20
 *
 
21
 * You should have received a copy of the GNU General Public License
 
22
 * along with this program; if not, write to the Free Software
 
23
 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 
24
 *
 
25
 */
 
26
 
 
27
/* 
 
28
 *
 
29
 * exported functions:
 
30
 *
 
31
 * int drv_generic_graphic_init (char *section, char *driver);
 
32
 *   initializes the generic graphic driver
 
33
 *
 
34
 * int drv_generic_graphic_draw (WIDGET *W);
 
35
 *   renders Text widget into framebuffer
 
36
 *   calls drv_generic_graphic_real_blit()
 
37
 *
 
38
 * int drv_generic_graphic_icon_draw (WIDGET *W);
 
39
 *   renders Icon widget into framebuffer
 
40
 *   calls drv_generic_graphic_real_blit()
 
41
 *
 
42
 * int drv_generic_graphic_bar_draw (WIDGET *W);
 
43
 *   renders Bar widget into framebuffer
 
44
 *   calls drv_generic_graphic_real_blit()
 
45
 *
 
46
 * int drv_generic_graphic_quit (void);
 
47
 *   closes generic graphic driver
 
48
 *
 
49
 */
 
50
 
 
51
 
 
52
#include "config.h"
 
53
 
 
54
#include <stdlib.h>
 
55
#include <stdio.h>
 
56
#include <string.h>
 
57
#include <errno.h>
 
58
#include <unistd.h>
 
59
#include <termios.h>
 
60
#include <fcntl.h>
 
61
 
 
62
#include "debug.h"
 
63
#include "cfg.h"
 
64
#include "plugin.h"
 
65
#include "layout.h"
 
66
#include "widget.h"
 
67
#include "property.h"
 
68
#include "widget_text.h"
 
69
#include "widget_icon.h"
 
70
#include "widget_bar.h"
 
71
#include "widget_image.h"
 
72
#include "rgb.h"
 
73
#include "drv.h"
 
74
#include "drv_generic.h"
 
75
#include "drv_generic_graphic.h"
 
76
#include "font_6x8.h"
 
77
#include "font_6x8_bold.h"
 
78
 
 
79
#ifdef WITH_DMALLOC
 
80
#include <dmalloc.h>
 
81
#endif
 
82
 
 
83
/* pixel colors */
 
84
RGBA FG_COL = {.R = 0x00,.G = 0x00,.B = 0x00,.A = 0xff };
 
85
RGBA BG_COL = {.R = 0xff,.G = 0xff,.B = 0xff,.A = 0xff };
 
86
RGBA BL_COL = {.R = 0xff,.G = 0xff,.B = 0xff,.A = 0x00 };
 
87
RGBA NO_COL = {.R = 0x00,.G = 0x00,.B = 0x00,.A = 0x00 };
 
88
 
 
89
static char *Section = NULL;
 
90
static char *Driver = NULL;
 
91
 
 
92
/* framebuffer */
 
93
static RGBA *drv_generic_graphic_FB[LAYERS] = { NULL, };
 
94
 
 
95
/* inverted colors */
 
96
static int INVERTED = 0;
 
97
 
 
98
/* must be implemented by the real driver */
 
99
void (*drv_generic_graphic_real_blit) () = NULL;
 
100
 
 
101
 
 
102
/****************************************/
 
103
/*** generic Framebuffer stuff        ***/
 
104
/****************************************/
 
105
 
 
106
static void drv_generic_graphic_resizeFB(int rows, int cols)
 
107
{
 
108
    RGBA *newFB;
 
109
    int i, l, row, col;
 
110
 
 
111
    /* Layout FB is large enough */
 
112
    if (rows <= LROWS && cols <= LCOLS)
 
113
        return;
 
114
 
 
115
    /* get maximum values */
 
116
    if (rows < LROWS)
 
117
        rows = LROWS;
 
118
    if (cols < LCOLS)
 
119
        cols = LCOLS;
 
120
 
 
121
    for (l = 0; l < LAYERS; l++) {
 
122
 
 
123
        /* allocate and initialize new Layout FB */
 
124
        newFB = malloc(cols * rows * sizeof(*newFB));
 
125
        for (i = 0; i < rows * cols; i++)
 
126
            newFB[i] = NO_COL;
 
127
 
 
128
        /* transfer contents */
 
129
        if (drv_generic_graphic_FB[l] != NULL) {
 
130
            for (row = 0; row < LROWS; row++) {
 
131
                for (col = 0; col < LCOLS; col++) {
 
132
                    newFB[row * cols + col] = drv_generic_graphic_FB[l][row * LCOLS + col];
 
133
                }
 
134
            }
 
135
            free(drv_generic_graphic_FB[l]);
 
136
        }
 
137
        drv_generic_graphic_FB[l] = newFB;
 
138
    }
 
139
 
 
140
    LCOLS = cols;
 
141
    LROWS = rows;
 
142
 
 
143
}
 
144
 
 
145
static void drv_generic_graphic_window(int pos, int size, int max, int *wpos, int *wsize)
 
146
{
 
147
    int p1 = pos;
 
148
    int p2 = pos + size;
 
149
 
 
150
    *wpos = 0;
 
151
    *wsize = 0;
 
152
 
 
153
    if (p1 > max || p2 < 0 || size < 1)
 
154
        return;
 
155
 
 
156
    if (p1 < 0)
 
157
        p1 = 0;
 
158
 
 
159
    if (p2 > max)
 
160
        p2 = max;
 
161
 
 
162
    *wpos = p1;
 
163
    *wsize = p2 - p1;
 
164
}
 
165
 
 
166
static void drv_generic_graphic_blit(const int row, const int col, const int height, const int width)
 
167
{
 
168
    if (drv_generic_graphic_real_blit) {
 
169
        int r, c, h, w;
 
170
        drv_generic_graphic_window(row, height, DROWS, &r, &h);
 
171
        drv_generic_graphic_window(col, width, DCOLS, &c, &w);
 
172
        if (h > 0 && w > 0) {
 
173
            drv_generic_graphic_real_blit(r, c, h, w);
 
174
        }
 
175
    }
 
176
}
 
177
 
 
178
static RGBA drv_generic_graphic_blend(const int row, const int col)
 
179
{
 
180
    int l, o;
 
181
    RGBA p;
 
182
    RGBA ret;
 
183
 
 
184
    ret.R = BL_COL.R;
 
185
    ret.G = BL_COL.G;
 
186
    ret.B = BL_COL.B;
 
187
    ret.A = 0x00;
 
188
 
 
189
    /* find first opaque layer */
 
190
    /* layers below are fully covered */
 
191
    o = LAYERS - 1;
 
192
    for (l = 0; l < LAYERS; l++) {
 
193
        p = drv_generic_graphic_FB[l][row * LCOLS + col];
 
194
        if (p.A == 255) {
 
195
            o = l;
 
196
            break;
 
197
        }
 
198
    }
 
199
 
 
200
    for (l = o; l >= 0; l--) {
 
201
        p = drv_generic_graphic_FB[l][row * LCOLS + col];
 
202
        switch (p.A) {
 
203
        case 0:
 
204
            break;
 
205
        case 255:
 
206
            ret.R = p.R;
 
207
            ret.G = p.G;
 
208
            ret.B = p.B;
 
209
            ret.A = 0xff;
 
210
            break;
 
211
        default:
 
212
            ret.R = (p.R * p.A + ret.R * (255 - p.A)) / 255;
 
213
            ret.G = (p.G * p.A + ret.G * (255 - p.A)) / 255;
 
214
            ret.B = (p.B * p.A + ret.B * (255 - p.A)) / 255;
 
215
            ret.A = 0xff;
 
216
        }
 
217
    }
 
218
    if (INVERTED) {
 
219
        ret.R = 255 - ret.R;
 
220
        ret.G = 255 - ret.G;
 
221
        ret.B = 255 - ret.B;
 
222
    }
 
223
 
 
224
    return ret;
 
225
}
 
226
 
 
227
 
 
228
/****************************************/
 
229
/*** generic text handling            ***/
 
230
/****************************************/
 
231
 
 
232
static void drv_generic_graphic_render(const int layer, const int row, const int col, const RGBA fg, const RGBA bg,
 
233
                                       const char *style, const char *txt)
 
234
{
 
235
    int c, r, x, y, len;
 
236
 
 
237
    /* sanity checks */
 
238
    if (layer < 0 || layer >= LAYERS) {
 
239
        error("%s: layer %d out of bounds (0..%d)", Driver, layer, LAYERS - 1);
 
240
        return;
 
241
    }
 
242
 
 
243
    len = strlen(txt);
 
244
 
 
245
    /* maybe grow layout framebuffer */
 
246
    drv_generic_graphic_resizeFB(row + YRES, col + XRES * len);
 
247
 
 
248
    r = row;
 
249
    c = col;
 
250
 
 
251
    /* render text into layout FB */
 
252
    while (*txt != '\0') {
 
253
        unsigned char *chr;
 
254
 
 
255
        if (strstr(style, "bold") != NULL) {
 
256
            chr = Font_6x8_bold[(int) *(unsigned char *) txt];
 
257
        } else {
 
258
            chr = Font_6x8[(int) *(unsigned char *) txt];
 
259
        }
 
260
 
 
261
        for (y = 0; y < YRES; y++) {
 
262
            int mask = 1 << XRES;
 
263
            for (x = 0; x < XRES; x++) {
 
264
                mask >>= 1;
 
265
                if (chr[y] & mask)
 
266
                    drv_generic_graphic_FB[layer][(r + y) * LCOLS + c + x] = fg;
 
267
                else
 
268
                    drv_generic_graphic_FB[layer][(r + y) * LCOLS + c + x] = bg;
 
269
            }
 
270
        }
 
271
        c += XRES;
 
272
        txt++;
 
273
    }
 
274
 
 
275
    /* flush area */
 
276
    drv_generic_graphic_blit(row, col, YRES, XRES * len);
 
277
 
 
278
}
 
279
 
 
280
 
 
281
/* say hello to the user */
 
282
int drv_generic_graphic_greet(const char *msg1, const char *msg2)
 
283
{
 
284
    char *line1[] = { "* LCD4Linux " VERSION " *",
 
285
        "LCD4Linux " VERSION,
 
286
        "* LCD4Linux *",
 
287
        "LCD4Linux",
 
288
        "L4Linux",
 
289
        NULL
 
290
    };
 
291
 
 
292
    char *line2[] = { "http://lcd4linux.bulix.org",
 
293
        "lcd4linux.bulix.org",
 
294
        NULL
 
295
    };
 
296
 
 
297
    int i;
 
298
    int flag = 0;
 
299
 
 
300
    unsigned int cols = DCOLS / XRES;
 
301
    unsigned int rows = DROWS / YRES;
 
302
 
 
303
    for (i = 0; line1[i]; i++) {
 
304
        if (strlen(line1[i]) <= cols) {
 
305
            drv_generic_graphic_render(0, YRES * 0, XRES * ((cols - strlen(line1[i])) / 2), FG_COL, BG_COL, "norm",
 
306
                                       line1[i]);
 
307
            flag = 1;
 
308
            break;
 
309
        }
 
310
    }
 
311
 
 
312
    if (rows >= 2) {
 
313
        for (i = 0; line2[i]; i++) {
 
314
            if (strlen(line2[i]) <= cols) {
 
315
                drv_generic_graphic_render(0, YRES * 1, XRES * ((cols - strlen(line2[i])) / 2), FG_COL, BG_COL, "norm",
 
316
                                           line2[i]);
 
317
                flag = 1;
 
318
                break;
 
319
            }
 
320
        }
 
321
    }
 
322
 
 
323
    if (msg1 && rows >= 3) {
 
324
        unsigned int len = strlen(msg1);
 
325
        if (len <= cols) {
 
326
            drv_generic_graphic_render(0, YRES * 2, XRES * ((cols - len) / 2), FG_COL, BG_COL, "norm", msg1);
 
327
            flag = 1;
 
328
        }
 
329
    }
 
330
 
 
331
    if (msg2 && rows >= 4) {
 
332
        unsigned int len = strlen(msg2);
 
333
        if (len <= cols) {
 
334
            drv_generic_graphic_render(0, YRES * 3, XRES * ((cols - len) / 2), FG_COL, BG_COL, "norm", msg2);
 
335
            flag = 1;
 
336
        }
 
337
    }
 
338
 
 
339
    return flag;
 
340
}
 
341
 
 
342
 
 
343
int drv_generic_graphic_draw(WIDGET * W)
 
344
{
 
345
    WIDGET_TEXT *Text = W->data;
 
346
    RGBA fg, bg;
 
347
 
 
348
    fg = W->fg_valid ? W->fg_color : FG_COL;
 
349
    bg = W->bg_valid ? W->bg_color : BG_COL;
 
350
 
 
351
    drv_generic_graphic_render(W->layer, YRES * W->row, XRES * W->col, fg, bg, P2S(&Text->style), Text->buffer);
 
352
 
 
353
    return 0;
 
354
}
 
355
 
 
356
 
 
357
/****************************************/
 
358
/*** generic icon handling            ***/
 
359
/****************************************/
 
360
 
 
361
int drv_generic_graphic_icon_draw(WIDGET * W)
 
362
{
 
363
    WIDGET_ICON *Icon = W->data;
 
364
    RGBA fg, bg;
 
365
    unsigned char *bitmap = Icon->bitmap + YRES * Icon->curmap;
 
366
    int layer, row, col;
 
367
    int x, y;
 
368
    int visible;
 
369
 
 
370
    layer = W->layer;
 
371
    row = YRES * W->row;
 
372
    col = XRES * W->col;
 
373
 
 
374
    fg = W->fg_valid ? W->fg_color : FG_COL;
 
375
    bg = W->bg_valid ? W->bg_color : BG_COL;
 
376
 
 
377
    /* sanity check */
 
378
    if (layer < 0 || layer >= LAYERS) {
 
379
        error("%s: layer %d out of bounds (0..%d)", Driver, layer, LAYERS - 1);
 
380
        return -1;
 
381
    }
 
382
 
 
383
    /* maybe grow layout framebuffer */
 
384
    drv_generic_graphic_resizeFB(row + YRES, col + XRES);
 
385
 
 
386
    /* Icon visible? */
 
387
    visible = P2N(&Icon->visible) > 0;
 
388
 
 
389
    /* render icon */
 
390
    for (y = 0; y < YRES; y++) {
 
391
        int mask = 1 << XRES;
 
392
        for (x = 0; x < XRES; x++) {
 
393
            int i = (row + y) * LCOLS + col + x;
 
394
            mask >>= 1;
 
395
            if (visible) {
 
396
                if (bitmap[y] & mask)
 
397
                    drv_generic_graphic_FB[layer][i] = fg;
 
398
                else
 
399
                    drv_generic_graphic_FB[layer][i] = bg;
 
400
            } else {
 
401
                drv_generic_graphic_FB[layer][i] = BG_COL;
 
402
            }
 
403
        }
 
404
    }
 
405
 
 
406
    /* flush area */
 
407
    drv_generic_graphic_blit(row, col, YRES, XRES);
 
408
 
 
409
    return 0;
 
410
 
 
411
}
 
412
 
 
413
 
 
414
/****************************************/
 
415
/*** generic bar handling             ***/
 
416
/****************************************/
 
417
 
 
418
int drv_generic_graphic_bar_draw(WIDGET * W)
 
419
{
 
420
    WIDGET_BAR *Bar = W->data;
 
421
    RGBA fg, bg, bar[2];
 
422
    int layer, row, col, len, res, rev, max, val1, val2;
 
423
    int x, y;
 
424
    DIRECTION dir;
 
425
    STYLE style;
 
426
 
 
427
    layer = W->layer;
 
428
    row = YRES * W->row;
 
429
    col = XRES * W->col;
 
430
    dir = Bar->direction;
 
431
    style = Bar->style;
 
432
    len = Bar->length;
 
433
 
 
434
    fg = W->fg_valid ? W->fg_color : FG_COL;
 
435
    bg = W->bg_valid ? W->bg_color : BG_COL;
 
436
 
 
437
    bar[0] = Bar->color_valid[0] ? Bar->color[0] : fg;
 
438
    bar[1] = Bar->color_valid[1] ? Bar->color[1] : fg;
 
439
 
 
440
    /* sanity check */
 
441
    if (layer < 0 || layer >= LAYERS) {
 
442
        error("%s: layer %d out of bounds (0..%d)", Driver, layer, LAYERS - 1);
 
443
        return -1;
 
444
    }
 
445
 
 
446
    /* maybe grow layout framebuffer */
 
447
    if (dir & (DIR_EAST | DIR_WEST)) {
 
448
        drv_generic_graphic_resizeFB(row + YRES, col + XRES * len);
 
449
    } else {
 
450
        drv_generic_graphic_resizeFB(row + YRES * len, col + XRES);
 
451
    }
 
452
 
 
453
    res = dir & (DIR_EAST | DIR_WEST) ? XRES : YRES;
 
454
    max = len * res;
 
455
    val1 = Bar->val1 * (double) (max);
 
456
    val2 = Bar->val2 * (double) (max);
 
457
 
 
458
    if (val1 < 1)
 
459
        val1 = 1;
 
460
    else if (val1 > max)
 
461
        val1 = max;
 
462
 
 
463
    if (val2 < 1)
 
464
        val2 = 1;
 
465
    else if (val2 > max)
 
466
        val2 = max;
 
467
 
 
468
    rev = 0;
 
469
 
 
470
    switch (dir) {
 
471
    case DIR_WEST:
 
472
        val1 = max - val1;
 
473
        val2 = max - val2;
 
474
        rev = 1;
 
475
 
 
476
    case DIR_EAST:
 
477
        for (y = 0; y < YRES; y++) {
 
478
            int val = y < YRES / 2 ? val1 : val2;
 
479
            RGBA bc = y < YRES / 2 ? bar[0] : bar[1];
 
480
 
 
481
            for (x = 0; x < max; x++) {
 
482
                if (x < val)
 
483
                    drv_generic_graphic_FB[layer][(row + y) * LCOLS + col + x] = rev ? bg : bc;
 
484
                else
 
485
                    drv_generic_graphic_FB[layer][(row + y) * LCOLS + col + x] = rev ? bc : bg;
 
486
 
 
487
                if (style) {
 
488
                    drv_generic_graphic_FB[layer][(row + 0) * LCOLS + col + x] = fg;
 
489
                    drv_generic_graphic_FB[layer][(row + YRES - 1) * LCOLS + col + x] = fg;
 
490
                }
 
491
            }
 
492
            if (style) {
 
493
                drv_generic_graphic_FB[layer][(row + y) * LCOLS + col] = fg;
 
494
                drv_generic_graphic_FB[layer][(row + y) * LCOLS + col + max - 1] = fg;
 
495
            }
 
496
        }
 
497
        break;
 
498
 
 
499
    case DIR_NORTH:
 
500
        val1 = max - val1;
 
501
        val2 = max - val2;
 
502
        rev = 1;
 
503
 
 
504
    case DIR_SOUTH:
 
505
        for (x = 0; x < XRES; x++) {
 
506
            int val = x < XRES / 2 ? val1 : val2;
 
507
            RGBA bc = x < XRES / 2 ? bar[0] : bar[1];
 
508
            for (y = 0; y < max; y++) {
 
509
                if (y < val)
 
510
                    drv_generic_graphic_FB[layer][(row + y) * LCOLS + col + x] = rev ? bg : bc;
 
511
                else
 
512
                    drv_generic_graphic_FB[layer][(row + y) * LCOLS + col + x] = rev ? bc : bg;
 
513
                if (style) {
 
514
                    drv_generic_graphic_FB[layer][(row + y) * LCOLS + col + 0] = fg;
 
515
                    drv_generic_graphic_FB[layer][(row + y) * LCOLS + col + XRES - 1] = fg;
 
516
                }
 
517
            }
 
518
            if (style) {
 
519
                drv_generic_graphic_FB[layer][(row + 0) * LCOLS + col + x] = fg;
 
520
                drv_generic_graphic_FB[layer][(row + max - 1) * LCOLS + col + x] = fg;
 
521
            }
 
522
        }
 
523
        break;
 
524
    }
 
525
 
 
526
    /* flush area */
 
527
    if (dir & (DIR_EAST | DIR_WEST)) {
 
528
        drv_generic_graphic_blit(row, col, YRES, XRES * len);
 
529
    } else {
 
530
        drv_generic_graphic_blit(row, col, YRES * len, XRES);
 
531
    }
 
532
 
 
533
    return 0;
 
534
}
 
535
 
 
536
 
 
537
/****************************************/
 
538
/*** generic image handling           ***/
 
539
/****************************************/
 
540
 
 
541
int drv_generic_graphic_image_draw(WIDGET * W)
 
542
{
 
543
    WIDGET_IMAGE *Image = W->data;
 
544
    int layer, row, col, width, height;
 
545
    int x, y;
 
546
    int visible;
 
547
 
 
548
    layer = W->layer;
 
549
    row = W->row;
 
550
    col = W->col;
 
551
    width = Image->width;
 
552
    height = Image->height;
 
553
 
 
554
    /* sanity check */
 
555
    if (layer < 0 || layer >= LAYERS) {
 
556
        error("%s: layer %d out of bounds (0..%d)", Driver, layer, LAYERS - 1);
 
557
        return -1;
 
558
    }
 
559
 
 
560
    /* if no size or no image at all, do nothing */
 
561
    if (width <= 0 || height <= 0 || Image->bitmap == NULL) {
 
562
        return 0;
 
563
    }
 
564
 
 
565
    /* maybe grow layout framebuffer */
 
566
    drv_generic_graphic_resizeFB(row + height, col + width);
 
567
 
 
568
    /* render image */
 
569
    visible = P2N(&Image->visible);
 
570
    for (y = 0; y < height; y++) {
 
571
        for (x = 0; x < width; x++) {
 
572
            int i = (row + y) * LCOLS + col + x;
 
573
            if (visible) {
 
574
                drv_generic_graphic_FB[layer][i] = Image->bitmap[y * width + x];
 
575
            } else {
 
576
                drv_generic_graphic_FB[layer][i] = BG_COL;
 
577
            }
 
578
        }
 
579
    }
 
580
 
 
581
    /* flush area */
 
582
    drv_generic_graphic_blit(row, col, height, width);
 
583
 
 
584
    return 0;
 
585
 
 
586
}
 
587
 
 
588
 
 
589
/****************************************/
 
590
/*** generic init/quit                ***/
 
591
/****************************************/
 
592
 
 
593
int drv_generic_graphic_init(const char *section, const char *driver)
 
594
{
 
595
    int i, l;
 
596
    char *color;
 
597
    WIDGET_CLASS wc;
 
598
 
 
599
    Section = (char *) section;
 
600
    Driver = (char *) driver;
 
601
 
 
602
    /* init layout framebuffer */
 
603
    LROWS = 0;
 
604
    LCOLS = 0;
 
605
 
 
606
    for (l = 0; l < LAYERS; l++)
 
607
        drv_generic_graphic_FB[l] = NULL;
 
608
 
 
609
    drv_generic_graphic_resizeFB(DROWS, DCOLS);
 
610
 
 
611
    /* sanity check */
 
612
    for (l = 0; l < LAYERS; l++) {
 
613
        if (drv_generic_graphic_FB[l] == NULL) {
 
614
            error("%s: framebuffer could not be allocated: malloc() failed", Driver);
 
615
            return -1;
 
616
        }
 
617
    }
 
618
 
 
619
    /* init generic driver & register plugins */
 
620
    drv_generic_init();
 
621
 
 
622
    /* set default colors */
 
623
    color = cfg_get(Section, "foreground", "000000ff");
 
624
    if (color2RGBA(color, &FG_COL) < 0) {
 
625
        error("%s: ignoring illegal color '%s'", Driver, color);
 
626
    }
 
627
    if (color)
 
628
        free(color);
 
629
 
 
630
    color = cfg_get(Section, "background", "ffffff00");
 
631
    if (color2RGBA(color, &BG_COL) < 0) {
 
632
        error("%s: ignoring illegal color '%s'", Driver, color);
 
633
    }
 
634
    if (color)
 
635
        free(color);
 
636
 
 
637
    color = cfg_get(Section, "basecolor", "ffffff");
 
638
    if (color2RGBA(color, &BL_COL) < 0) {
 
639
        error("%s: ignoring illegal color '%s'", Driver, color);
 
640
    }
 
641
    if (color)
 
642
        free(color);
 
643
 
 
644
    /* inverted display? */
 
645
    cfg_number(section, "inverted", 0, 0, 1, &INVERTED);
 
646
 
 
647
    /* register text widget */
 
648
    wc = Widget_Text;
 
649
    wc.draw = drv_generic_graphic_draw;
 
650
    widget_register(&wc);
 
651
 
 
652
    /* register icon widget */
 
653
    wc = Widget_Icon;
 
654
    wc.draw = drv_generic_graphic_icon_draw;
 
655
    widget_register(&wc);
 
656
 
 
657
    /* register bar widget */
 
658
    wc = Widget_Bar;
 
659
    wc.draw = drv_generic_graphic_bar_draw;
 
660
    widget_register(&wc);
 
661
 
 
662
    /* register image widget */
 
663
#ifdef WITH_IMAGE
 
664
    wc = Widget_Image;
 
665
    wc.draw = drv_generic_graphic_image_draw;
 
666
    widget_register(&wc);
 
667
#endif
 
668
 
 
669
    /* clear framebuffer but do not blit to display */
 
670
    for (l = 0; l < LAYERS; l++)
 
671
        for (i = 0; i < LCOLS * LROWS; i++)
 
672
            drv_generic_graphic_FB[l][i] = NO_COL;
 
673
 
 
674
    return 0;
 
675
}
 
676
 
 
677
 
 
678
int drv_generic_graphic_clear(void)
 
679
{
 
680
    int i, l;
 
681
 
 
682
    for (l = 0; l < LAYERS; l++)
 
683
        for (i = 0; i < LCOLS * LROWS; i++)
 
684
            drv_generic_graphic_FB[l][i] = NO_COL;
 
685
 
 
686
    drv_generic_graphic_blit(0, 0, LROWS, LCOLS);
 
687
 
 
688
    return 0;
 
689
}
 
690
 
 
691
 
 
692
RGBA drv_generic_graphic_rgb(const int row, const int col)
 
693
{
 
694
    return drv_generic_graphic_blend(row, col);
 
695
}
 
696
 
 
697
 
 
698
unsigned char drv_generic_graphic_gray(const int row, const int col)
 
699
{
 
700
    RGBA p = drv_generic_graphic_blend(row, col);
 
701
    return (77 * p.R + 150 * p.G + 28 * p.B) / 255;
 
702
}
 
703
 
 
704
 
 
705
unsigned char drv_generic_graphic_black(const int row, const int col)
 
706
{
 
707
    return drv_generic_graphic_gray(row, col) < 127;
 
708
}
 
709
 
 
710
 
 
711
int drv_generic_graphic_quit(void)
 
712
{
 
713
    int l;
 
714
 
 
715
    for (l = 0; l < LAYERS; l++) {
 
716
        if (drv_generic_graphic_FB[l]) {
 
717
            free(drv_generic_graphic_FB[l]);
 
718
            drv_generic_graphic_FB[l] = NULL;
 
719
        }
 
720
    }
 
721
    widget_unregister();
 
722
    return (0);
 
723
}