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