source: toilet/trunk/src/render.c @ 1195

Last change on this file since 1195 was 1195, checked in by Sam Hocevar, 15 years ago
  • Properly handle \r \n \t in the big and tiny renderers.
  • Property svn:keywords set to Id
File size: 4.2 KB
Line 
1/*
2 *  TOIlet        The Other Implementation’s letters
3 *  Copyright (c) 2006 Sam Hocevar <sam@zoy.org>
4 *                All Rights Reserved
5 *
6 *  $Id: render.c 1195 2006-10-10 07:15:28Z sam $
7 *
8 *  This program is free software; you can redistribute it and/or
9 *  modify it under the terms of the Do What The Fuck You Want To
10 *  Public License, Version 2, as published by Sam Hocevar. See
11 *  http://sam.zoy.org/wtfpl/COPYING for more details.
12 */
13
14/*
15 * This file contains text to canvas rendering functions.
16 */
17
18#include "config.h"
19
20#if defined(HAVE_INTTYPES_H)
21#   include <inttypes.h>
22#endif
23#include <stdlib.h>
24#include <cucul.h>
25
26#include "toilet.h"
27#include "render.h"
28
29static int feed_tiny(context_t *, uint32_t);
30static int end_tiny(context_t *);
31
32static int feed_big(context_t *, uint32_t);
33static int end_big(context_t *);
34
35int init_tiny(context_t *cx)
36{
37    cx->ew = 16;
38    cx->eh = 2;
39    cx->x = cx->y = 0;
40    cx->w = cx->h = 0;
41    cx->cv = cucul_create_canvas(cx->ew, cx->eh);
42
43    cx->feed = feed_tiny;
44    cx->end = end_tiny;
45
46    return 0;
47}
48
49static int feed_tiny(context_t *cx, uint32_t ch)
50{
51    switch(ch)
52    {
53        case (uint32_t)'\r':
54            return 0;
55        case (uint32_t)'\n':
56            cx->x = 0;
57            cx->y++;
58            return 0;
59        case (uint32_t)'\t':
60            cx->x = (cx->x & ~7) + 8;
61            return 0;
62    }
63
64    /* Check whether we reached the end of the screen */
65    if(cx->x && cx->x + 1 > cx->term_width)
66    {
67        cx->x = 0;
68        cx->y++;
69    }
70
71    /* Check whether the current canvas is large enough */
72    if(cx->x + 1 > cx->w)
73    {
74        cx->w = cx->x + 1 < cx->term_width ? cx->x + 1 : cx->term_width;
75        if(cx->w > cx->ew)
76            cx->ew = cx->ew + cx->ew / 2;
77    }
78
79    if(cx->y + 1 > cx->h)
80    {
81        cx->h = cx->y + 1;
82        if(cx->h > cx->eh)
83            cx->eh = cx->eh + cx->eh / 2;
84    }
85
86    cucul_set_canvas_size(cx->cv, cx->ew, cx->eh);
87
88    cucul_putchar(cx->cv, cx->x, cx->y, ch);
89    cx->x++;
90
91    return 0;
92}
93
94static int end_tiny(context_t *cx)
95{
96    cucul_set_canvas_size(cx->cv, cx->w, cx->h);
97
98    return 0;
99}
100
101int init_big(context_t *cx)
102{
103    char const * const * fonts;
104
105    fonts = cucul_get_font_list();
106    cx->f = cucul_load_font(fonts[0], 0);
107    cx->buf = malloc(4 * cucul_get_font_width(cx->f)
108                       * cucul_get_font_height(cx->f));
109    cx->onechar = cucul_create_canvas(1, 1);
110    cucul_set_color(cx->onechar, CUCUL_COLOR_WHITE, CUCUL_COLOR_BLACK);
111
112    cx->x = cx->y = 0;
113    cx->w = cx->h = 0;
114    cx->cv = cucul_create_canvas(1, 1);
115
116    cx->feed = feed_big;
117    cx->end = end_big;
118
119    return 0;
120}
121
122static int feed_big(context_t *cx, uint32_t ch)
123{
124    unsigned int w = cucul_get_font_width(cx->f);
125    unsigned int h = cucul_get_font_height(cx->f);
126    unsigned int x, y;
127
128    switch(ch)
129    {
130        case (uint32_t)'\r':
131            return 0;
132        case (uint32_t)'\n':
133            cx->x = 0;
134            cx->y += h;
135            return 0;
136        case (uint32_t)'\t':
137            cx->x = (((cx->x / w) & ~7) + 8) * w;
138            return 0;
139    }
140
141    /* Check whether we reached the end of the screen */
142    if(cx->x && cx->x + w > cx->term_width)
143    {
144        cx->x = 0;
145        cx->y += h;
146    }
147
148    /* Check whether the current canvas is large enough */
149    if(cx->x + w > cx->w)
150        cx->w = cx->x + w < cx->term_width ? cx->x + w : cx->term_width;
151
152    if(cx->y + h > cx->h)
153        cx->h = cx->y + h;
154
155    cucul_set_canvas_size(cx->cv, cx->w, cx->h);
156
157    /* Render our char */
158    cucul_putchar(cx->onechar, 0, 0, ch);
159    cucul_render_canvas(cx->onechar, cx->f, cx->buf, w, h, 4 * w);
160
161    for(y = 0; y < h; y++)
162       for(x = 0; x < w; x++)
163    {
164        unsigned char c = cx->buf[4 * (x + y * w) + 2];
165
166        if(c >= 0xa0)
167            cucul_putstr(cx->cv, cx->x + x, cx->y + y, "█");
168        else if(c >= 0x80)
169            cucul_putstr(cx->cv, cx->x + x, cx->y + y, "▓");
170        else if(c >= 0x40)
171            cucul_putstr(cx->cv, cx->x + x, cx->y + y, "▒");
172        else if(c >= 0x20)
173            cucul_putstr(cx->cv, cx->x + x, cx->y + y, "░");
174    }
175
176    /* Advance cursor */
177    cx->x += w;
178
179    return 0;
180}
181
182static int end_big(context_t *cx)
183{
184    cucul_free_canvas(cx->onechar);
185    free(cx->buf);
186    cucul_free_font(cx->f);
187
188    return 0;
189}
190
Note: See TracBrowser for help on using the repository browser.