1 | /* |
---|
2 | * libcaca Colour ASCII-Art library |
---|
3 | * Copyright (c) 2002-2006 Sam Hocevar <sam@zoy.org> |
---|
4 | * All Rights Reserved |
---|
5 | * |
---|
6 | * $Id: caca0.c 1462 2006-12-12 01:53:54Z sam $ |
---|
7 | * |
---|
8 | * This library is free software. It comes without any warranty, to |
---|
9 | * the extent permitted by applicable law. You can redistribute it |
---|
10 | * and/or modify it under the terms of the Do What The Fuck You Want |
---|
11 | * To Public License, Version 2, as published by Sam Hocevar. See |
---|
12 | * http://sam.zoy.org/wtfpl/COPYING for more details. |
---|
13 | */ |
---|
14 | |
---|
15 | /* |
---|
16 | * This file contains glue code for applications using the pre-1.0 |
---|
17 | * libcaca API. |
---|
18 | */ |
---|
19 | |
---|
20 | #include "config.h" |
---|
21 | #include "common.h" |
---|
22 | |
---|
23 | #if !defined(__KERNEL__) |
---|
24 | # include <stdlib.h> |
---|
25 | #endif |
---|
26 | |
---|
27 | #include "caca.h" |
---|
28 | #include "caca_internals.h" |
---|
29 | |
---|
30 | /* These variables are needed to emulate old non-thread safe behaviour */ |
---|
31 | cucul_canvas_t *__caca0_cv = NULL; |
---|
32 | caca_display_t *__caca0_dp = NULL; |
---|
33 | unsigned char __caca0_fg = CUCUL_LIGHTGRAY; |
---|
34 | unsigned char __caca0_bg = CUCUL_BLACK; |
---|
35 | char __caca0_utf8[2] = " "; |
---|
36 | |
---|
37 | /* These functions are needed, too */ |
---|
38 | int __caca0_init(void); |
---|
39 | void __caca0_end(void); |
---|
40 | unsigned int __caca0_get_event(unsigned int, int); |
---|
41 | unsigned int __caca0_sqrt(unsigned int); |
---|
42 | int __caca0_get_feature(int); |
---|
43 | void __caca0_set_feature(int); |
---|
44 | char const *__caca0_get_feature_name(int); |
---|
45 | cucul_canvas_t *__caca0_load_sprite(char const *); |
---|
46 | cucul_dither_t *__caca0_create_bitmap(unsigned int, unsigned int, |
---|
47 | unsigned int, unsigned int, unsigned long int, unsigned long int, |
---|
48 | unsigned long int, unsigned long int); |
---|
49 | void __caca0_free_bitmap(cucul_dither_t *); |
---|
50 | extern char const *__caca0_get_color_name(unsigned char); |
---|
51 | |
---|
52 | /* Emulation functions */ |
---|
53 | int __caca0_init(void) |
---|
54 | { |
---|
55 | __caca0_cv = cucul_create_canvas(0, 0); |
---|
56 | if(!__caca0_cv) |
---|
57 | return -1; |
---|
58 | __caca0_dp = caca_create_display(__caca0_cv); |
---|
59 | if(!__caca0_dp) |
---|
60 | { |
---|
61 | cucul_free_canvas(__caca0_cv); |
---|
62 | __caca0_cv = NULL; |
---|
63 | return -1; |
---|
64 | } |
---|
65 | __caca0_fg = CUCUL_LIGHTGRAY; |
---|
66 | __caca0_bg = CUCUL_BLACK; |
---|
67 | return 0; |
---|
68 | } |
---|
69 | |
---|
70 | void __caca0_end(void) |
---|
71 | { |
---|
72 | caca_free_display(__caca0_dp); |
---|
73 | __caca0_dp = NULL; |
---|
74 | cucul_free_canvas(__caca0_cv); |
---|
75 | __caca0_cv = NULL; |
---|
76 | } |
---|
77 | |
---|
78 | unsigned int __caca0_get_event(unsigned int m, int t) |
---|
79 | { |
---|
80 | caca_event_t ev; |
---|
81 | int ret; |
---|
82 | |
---|
83 | ret = caca_get_event(__caca0_dp, (m >> 24) & 0x7f, &ev, t); |
---|
84 | if(!ret) |
---|
85 | return 0x00000000; |
---|
86 | |
---|
87 | switch(ev.type) |
---|
88 | { |
---|
89 | case CACA_EVENT_KEY_PRESS: |
---|
90 | return 0x01000000 | ev.data.key.ch; |
---|
91 | case CACA_EVENT_KEY_RELEASE: |
---|
92 | return 0x02000000 | ev.data.key.ch; |
---|
93 | case CACA_EVENT_MOUSE_PRESS: |
---|
94 | return 0x04000000 | ev.data.mouse.button; |
---|
95 | case CACA_EVENT_MOUSE_RELEASE: |
---|
96 | return 0x08000000 | ev.data.mouse.button; |
---|
97 | case CACA_EVENT_MOUSE_MOTION: |
---|
98 | return 0x10000000 | ((ev.data.mouse.x & 0xfff) << 12) |
---|
99 | | (ev.data.mouse.y & 0xfff); |
---|
100 | case CACA_EVENT_RESIZE: |
---|
101 | return 0x20000000; |
---|
102 | default: |
---|
103 | break; |
---|
104 | } |
---|
105 | |
---|
106 | return 0x00000000; |
---|
107 | } |
---|
108 | |
---|
109 | unsigned int __caca0_sqrt(unsigned int a) |
---|
110 | { |
---|
111 | if(a == 0) |
---|
112 | return 0; |
---|
113 | |
---|
114 | if(a < 1000000000) |
---|
115 | { |
---|
116 | unsigned int x = a < 10 ? 1 |
---|
117 | : a < 1000 ? 10 |
---|
118 | : a < 100000 ? 100 |
---|
119 | : a < 10000000 ? 1000 |
---|
120 | : 10000; |
---|
121 | |
---|
122 | /* Newton's method. Three iterations would be more than enough. */ |
---|
123 | x = (x * x + a) / x / 2; |
---|
124 | x = (x * x + a) / x / 2; |
---|
125 | x = (x * x + a) / x / 2; |
---|
126 | x = (x * x + a) / x / 2; |
---|
127 | |
---|
128 | return x; |
---|
129 | } |
---|
130 | |
---|
131 | return 2 * __caca0_sqrt(a / 4); |
---|
132 | } |
---|
133 | |
---|
134 | static char const *features[] = |
---|
135 | { |
---|
136 | NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, |
---|
137 | NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, |
---|
138 | |
---|
139 | NULL, "16", "full16", NULL, NULL, NULL, NULL, NULL, |
---|
140 | NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, |
---|
141 | |
---|
142 | NULL, "none", "prefilter", NULL, NULL, NULL, NULL, NULL, |
---|
143 | NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, |
---|
144 | |
---|
145 | NULL, "none", "ordered2", "ordered4", "ordered8", "random" |
---|
146 | }; |
---|
147 | |
---|
148 | static cucul_dither_t **bitmaps = NULL; |
---|
149 | static unsigned int nbitmaps = 0; |
---|
150 | |
---|
151 | static int background = 0x12; |
---|
152 | static int antialiasing = 0x22; |
---|
153 | static int dithering = 0x33; |
---|
154 | |
---|
155 | int __caca0_get_feature(int feature) |
---|
156 | { |
---|
157 | if(feature == 0x10) |
---|
158 | return background; |
---|
159 | if(feature == 0x20) |
---|
160 | return antialiasing; |
---|
161 | if(feature == 0x30) |
---|
162 | return dithering; |
---|
163 | return 0xffff; /* CACA_FEATURE_UNKNOWN */ |
---|
164 | } |
---|
165 | |
---|
166 | void __caca0_set_feature(int feature) |
---|
167 | { |
---|
168 | unsigned int i; |
---|
169 | |
---|
170 | switch(feature) |
---|
171 | { |
---|
172 | case 0x10: feature = 0x12; /* CACA_BACKGROUND_SOLID */ |
---|
173 | case 0x11: case 0x12: |
---|
174 | background = feature; |
---|
175 | for(i = 0; i < nbitmaps; i++) |
---|
176 | cucul_set_dither_color(bitmaps[i], features[feature]); |
---|
177 | break; |
---|
178 | |
---|
179 | case 0x20: feature = 0x22; /* CACA_ANTIALIASING_PREFILTER */ |
---|
180 | case 0x21: case 0x22: |
---|
181 | antialiasing = feature; |
---|
182 | for(i = 0; i < nbitmaps; i++) |
---|
183 | cucul_set_dither_antialias(bitmaps[i], features[feature]); |
---|
184 | break; |
---|
185 | |
---|
186 | case 0x30: feature = 0x33; /* CACA_DITHERING_ORDERED4 */ |
---|
187 | case 0x31: case 0x32: case 0x33: case 0x34: case 0x35: |
---|
188 | dithering = feature; |
---|
189 | for(i = 0; i < nbitmaps; i++) |
---|
190 | cucul_set_dither_mode(bitmaps[i], features[feature]); |
---|
191 | break; |
---|
192 | } |
---|
193 | } |
---|
194 | |
---|
195 | char const *__caca0_get_feature_name(int feature) |
---|
196 | { |
---|
197 | switch(feature) |
---|
198 | { |
---|
199 | case 0x11: return "black background"; |
---|
200 | case 0x12: return "solid background"; |
---|
201 | |
---|
202 | case 0x21: return "no antialiasing"; |
---|
203 | case 0x22: return "prefilter antialiasing"; |
---|
204 | |
---|
205 | case 0x31: return "no dithering"; |
---|
206 | case 0x32: return "2x2 ordered dithering"; |
---|
207 | case 0x33: return "4x4 ordered dithering"; |
---|
208 | case 0x34: return "8x8 ordered dithering"; |
---|
209 | case 0x35: return "random dithering"; |
---|
210 | |
---|
211 | default: return "unknown"; |
---|
212 | } |
---|
213 | } |
---|
214 | |
---|
215 | cucul_canvas_t *__caca0_load_sprite(char const *file) |
---|
216 | { |
---|
217 | cucul_canvas_t *cv; |
---|
218 | |
---|
219 | cv = cucul_create_canvas(0, 0);; |
---|
220 | if(cucul_import_file(cv, file, "") < 0) |
---|
221 | { |
---|
222 | cucul_free_canvas(cv); |
---|
223 | return NULL; |
---|
224 | } |
---|
225 | |
---|
226 | return cv; |
---|
227 | } |
---|
228 | |
---|
229 | cucul_dither_t *__caca0_create_bitmap(unsigned int bpp, unsigned int w, |
---|
230 | unsigned int h, unsigned int pitch, |
---|
231 | unsigned long int r, unsigned long int g, |
---|
232 | unsigned long int b, unsigned long int a) |
---|
233 | { |
---|
234 | cucul_dither_t *d; |
---|
235 | |
---|
236 | d = cucul_create_dither(bpp, w, h, pitch, r, g, b, a); |
---|
237 | if(!d) |
---|
238 | return NULL; |
---|
239 | |
---|
240 | cucul_set_dither_color(d, features[background]); |
---|
241 | cucul_set_dither_antialias(d, features[antialiasing]); |
---|
242 | cucul_set_dither_mode(d, features[dithering]); |
---|
243 | |
---|
244 | /* Store bitmap in our list */ |
---|
245 | nbitmaps++; |
---|
246 | bitmaps = realloc(bitmaps, nbitmaps * (sizeof(cucul_dither_t *))); |
---|
247 | bitmaps[nbitmaps - 1] = d; |
---|
248 | |
---|
249 | return d; |
---|
250 | } |
---|
251 | |
---|
252 | void __caca0_free_bitmap(cucul_dither_t *d) |
---|
253 | { |
---|
254 | unsigned int i, found = 0; |
---|
255 | |
---|
256 | cucul_free_dither(d); |
---|
257 | |
---|
258 | /* Remove bitmap from our list */ |
---|
259 | for(i = 0; i + 1 < nbitmaps; i++) |
---|
260 | { |
---|
261 | if(bitmaps[i] == d) |
---|
262 | found = 1; |
---|
263 | if(found) |
---|
264 | bitmaps[i] = bitmaps[i + 1]; |
---|
265 | } |
---|
266 | |
---|
267 | nbitmaps--; |
---|
268 | } |
---|
269 | |
---|
270 | char const *__caca0_get_color_name(unsigned char color) |
---|
271 | { |
---|
272 | static char const *color_names[] = |
---|
273 | { |
---|
274 | "black", |
---|
275 | "blue", |
---|
276 | "green", |
---|
277 | "cyan", |
---|
278 | "red", |
---|
279 | "magenta", |
---|
280 | "brown", |
---|
281 | "light gray", |
---|
282 | "dark gray", |
---|
283 | "light blue", |
---|
284 | "light green", |
---|
285 | "light cyan", |
---|
286 | "light red", |
---|
287 | "light magenta", |
---|
288 | "yellow", |
---|
289 | "white", |
---|
290 | }; |
---|
291 | |
---|
292 | if(color > 15) |
---|
293 | return "unknown"; |
---|
294 | |
---|
295 | return color_names[(unsigned int)color]; |
---|
296 | } |
---|
297 | |
---|