b7964a6c31bbb05062a8288b4d7fe7c060a3e4b9
[xscreensaver] / android / jwxyz.c
1 /* xscreensaver, Copyright (c) 1991-2014 Jamie Zawinski <jwz@jwz.org>
2  *
3  * Permission to use, copy, modify, distribute, and sell this software and its
4  * documentation for any purpose is hereby granted without fee, provided that
5  * the above copyright notice appear in all copies and that both that
6  * copyright notice and this permission notice appear in supporting
7  * documentation.  No representations are made about the suitability of this
8  * software for any purpose.  It is provided "as is" without express or 
9  * implied warranty.
10  */
11
12 /* JWXYZ Is Not Xlib.
13
14    But it's a bunch of function definitions that bear some resemblance to
15    Xlib and that do things that bear some resemblance to the
16    things that Xlib might have done.
17  */
18
19 #include <stdlib.h>
20 #include <stdint.h>
21 #include <wchar.h>
22 #include <android/log.h>
23
24 #include "jwxyz.h"
25 #include "jwxyz-timers.h"
26 #include "yarandom.h"
27 #include "screenhackI.h"
28
29 typedef signed char BOOL;
30 #define YES             (BOOL)1
31 #define NO              (BOOL)0
32
33 struct CGPoint {
34     float x;
35     float y;
36 };
37 typedef struct CGPoint CGPoint;
38
39 struct CGSize {
40     float width;
41     float height;
42 };
43 typedef struct CGSize CGSize;
44
45 struct CGRect {
46     CGPoint origin;
47     CGSize size;
48 };
49 typedef struct CGRect CGRect;
50
51 struct jwxyz_Drawable {
52     enum { WINDOW, PIXMAP } type;
53     CGRect frame;
54     union {
55         struct {
56             unsigned long background;
57             int last_mouse_x, last_mouse_y;
58         } window;
59         struct {
60             int depth;
61             void *cgc_buffer;   
62         } pixmap;
63     };
64 };
65
66 struct jwxyz_Display {
67     Window main_window;
68     Screen *screen;
69     int screen_count;
70     struct jwxyz_sources_data *timers_data;
71 };
72
73 struct jwxyz_Screen {
74     Display *dpy;
75     Visual *visual;
76     int screen_number;
77 };
78
79
80 static void draw_rect(Display *, Drawable, GC,
81                       int x, int y, unsigned int width,
82                       unsigned int height, BOOL foreground_p, BOOL fill_p);
83
84 Status
85 XParseColor(Display * dpy, Colormap cmap, const char *spec, XColor * ret)
86 {
87     unsigned char r = 0, g = 0, b = 0;
88     if (*spec == '#' && strlen(spec) == 7) {
89         static unsigned const char hex[] = {    // yeah yeah, shoot me.
90             0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
91                 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
92             0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 4,
93                 5, 6, 7, 8, 9, 0, 0, 0, 0, 0, 0,
94             0, 10, 11, 12, 13, 14, 15, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
95                 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
96             0, 10, 11, 12, 13, 14, 15, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
97                 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
98             0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
99                 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
100             0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
101                 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
102             0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
103                 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
104             0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
105                 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
106         };
107         r = (hex[spec[1]] << 4) | hex[spec[2]];
108         g = (hex[spec[3]] << 4) | hex[spec[4]];
109         b = (hex[spec[5]] << 4) | hex[spec[6]];
110     } else if (!strcasecmp(spec, "black")) {
111 //  r = g = b = 0;
112     } else if (!strcasecmp(spec, "white")) {
113         r = g = b = 255;
114     } else if (!strcasecmp(spec, "red")) {
115         r = 255;
116     } else if (!strcasecmp(spec, "green")) {
117         g = 255;
118     } else if (!strcasecmp(spec, "blue")) {
119         b = 255;
120     } else if (!strcasecmp(spec, "cyan")) {
121         g = b = 255;
122     } else if (!strcasecmp(spec, "magenta")) {
123         r = b = 255;
124     } else if (!strcasecmp(spec, "yellow")) {
125         r = g = 255;
126     } else {
127         return 0;
128     }
129
130     ret->red = (r << 8) | r;
131     ret->green = (g << 8) | g;
132     ret->blue = (b << 8) | b;
133     ret->flags = DoRed | DoGreen | DoBlue;
134     return 1;
135 }
136
137 Status XAllocColor(Display * dpy, Colormap cmap, XColor * color)
138 {
139     // store 32 bit ARGB in the pixel field.
140     // (The uint32_t is so that 0xFF000000 doesn't become 0xFFFFFFFFFF000000)
141     color->pixel = (uint32_t)
142         ((0xFF << 24) |
143          (((color->red >> 8) & 0xFF) << 16) |
144          (((color->green >> 8) & 0xFF) << 8) |
145          (((color->blue >> 8) & 0xFF)));
146     return 1;
147 }
148
149 //  needs to be implemented in Android...
150 int
151 XFillRectangle(Display * dpy, Drawable d, GC gc, int x, int y,
152                unsigned int width, unsigned int height)
153 {
154     return 0;
155 }
156
157 //  needs to be implemented in Android...
158 int
159 XDrawString(Display * dpy, Drawable d, GC gc, int x, int y,
160             const char *str, int len)
161 {
162     return 0;                   // try this for now...
163 }
164
165
166 //  needs to be implemented in Android...
167 int XFreeGC(Display * dpy, GC gc)
168 {
169     return 0;
170 }
171
172
173
174 int XFreeFont(Display * dpy, XFontStruct * f)
175 {
176     return 0;
177 }
178
179 int XFreeFontInfo(char **names, XFontStruct * info, int n)
180 {
181     int i;
182     if (names) {
183         for (i = 0; i < n; i++)
184             if (names[i])
185                 free(names[i]);
186         free(names);
187     }
188     if (info) {
189         for (i = 0; i < n; i++)
190             if (info[i].per_char)
191                 free(info[i].per_char);
192         free(info);
193     }
194     return 0;
195 }
196
197
198 //  needs to be implemented in Android...
199 int XUnloadFont(Display * dpy, Font fid)
200 {
201     return 0;
202 }
203
204
205 //  needs to be implemented in Android...
206 GC
207 XCreateGC(Display * dpy, Drawable d, unsigned long mask, XGCValues * xgcv)
208 {
209 }
210
211
212 //  needs to be implemented in Android...
213 XFontStruct *XLoadQueryFont(Display * dpy, const char *name)
214 {
215 }
216
217
218 Status
219 XGetWindowAttributes(Display * dpy, Window w, XWindowAttributes * xgwa)
220 {
221
222 //  Assert (w && w->type == WINDOW, "not a window");
223
224     memset(xgwa, 0, sizeof(*xgwa));
225     xgwa->x = w->frame.origin.x;
226     xgwa->y = w->frame.origin.y;
227     xgwa->width = w->frame.size.width;
228     xgwa->height = w->frame.size.height;
229     xgwa->depth = 32;
230     xgwa->screen = dpy->screen;
231     xgwa->visual = dpy->screen->visual;
232
233     return 0;
234 }
235
236 //  needs to be implemented in Android...
237 int XSetFont(Display * dpy, GC gc, Font fid)
238 {
239     return 0;
240 }
241
242
243 //  needs to be implemented in Android...
244 int XClearWindow(Display * dpy, Window win)
245 {
246 }
247
248 // declared in utils/visual.h
249 int has_writable_cells(Screen * s, Visual * v)
250 {
251     return 0;
252 }
253
254 Status
255 XAllocColorCells(Display * dpy, Colormap cmap, Bool contig,
256                  unsigned long *pmret, unsigned int npl,
257                  unsigned long *pxret, unsigned int npx)
258 {
259     return 0;
260 }
261
262 int XStoreColors(Display * dpy, Colormap cmap, XColor * colors, int n)
263 {
264     //Assert(0, "XStoreColors called");
265     return 0;
266 }
267
268 int
269 XFreeColors(Display * dpy, Colormap cmap, unsigned long *px, int npixels,
270             unsigned long planes)
271 {
272     return 0;
273 }
274
275 int XFlush(Display * dpy)
276 {
277     return 0;
278 }
279
280 Display *XDisplayOfScreen(Screen * s)
281 {
282     return s->dpy;
283 }
284
285 //  needs to be implemented in Android...
286 int
287 XLookupString(XKeyEvent * e, char *buf, int size, KeySym * k_ret,
288               XComposeStatus * xc)
289 {
290     return 0;
291 }
292
293 int XScreenNumberOfScreen(Screen * s)
294 {
295     return s->screen_number;
296 }
297
298 int jwxyz_ScreenCount(Display * dpy)
299 {
300     return dpy->screen_count;
301 }
302
303
304 /*
305 // should this be defined?
306 static Display *jwxyz_live_displays[20] = { 0, };
307 */
308
309 Display * jwxyz_make_display (void *nsview_arg, void *cgc_arg)
310 {
311     Display *d = (Display *) calloc(1, sizeof(*d));
312     d->screen = (Screen *) calloc(1, sizeof(Screen));
313     d->screen->dpy = d;
314
315     d->screen_count = 1;
316     d->screen->screen_number = 0;
317
318     Visual *v = (Visual *) calloc(1, sizeof(Visual));
319     v->class = TrueColor;
320     v->red_mask = 0x00FF0000;
321     v->green_mask = 0x0000FF00;
322     v->blue_mask = 0x000000FF;
323     v->bits_per_rgb = 8;
324     d->screen->visual = v;
325
326     Window w = (Window) calloc(1, sizeof(*w));
327     w->type = WINDOW;
328     w->window.background = BlackPixel(0, 0);
329
330     d->main_window = w;
331
332     return d;
333 }
334
335 void
336 jwxyz_free_display (Display *dpy)
337 {
338   free (dpy->screen->visual);
339   free (dpy->screen);
340   free (dpy->main_window);
341   free (dpy);
342 }
343
344
345 /* Call this when the Renderer calls onSurfaceChanged
346  */
347 void
348 jwxyz_window_resized (Display *dpy, Window w, 
349                       int new_x, int new_y, int new_width, int new_height,
350                       void *cgc_arg)
351 {
352     w->frame.origin.x = new_x;
353     w->frame.origin.y = new_y;
354     w->frame.size.width = new_width;
355     w->frame.size.height = new_height;
356 }
357
358 Window XRootWindow(Display * dpy, int screen)
359 {
360     return dpy->main_window;
361 }
362
363 /* Handle an abort on Android
364    TODO: Test that Android handles aborts properly
365  */
366 void
367 jwxyz_abort (const char *fmt, ...)
368 {
369   char s[10240];
370   if (!fmt || !*fmt)
371     strcpy (s, "abort");
372   else
373     {
374       va_list args;
375       va_start (args, fmt);
376       vsprintf (s, fmt, args);
377       va_end (args);
378     }
379   /* Send error to Android device log */
380   __android_log_write(ANDROID_LOG_ERROR, "xscreensaver", s);
381
382   abort();  
383 }
384
385 Pixmap
386 XCreatePixmap (Display *dpy, Drawable d,
387                unsigned int width, unsigned int height, unsigned int depth)
388 {
389 }
390
391 int
392 XDestroyImage (XImage *ximage)
393 {
394   if (ximage->data) free (ximage->data);
395   free (ximage);
396   return 0;
397 }
398
399 int
400 XDrawString16 (Display *dpy, Drawable d, GC gc, int x, int y,
401              const XChar2b *str, int len)
402 {
403 }
404
405 int
406 XFreePixmap (Display *d, Pixmap p)
407 {
408 }
409
410 XImage *
411 XGetImage (Display *dpy, Drawable d, int x, int y,
412            unsigned int width, unsigned int height,
413            unsigned long plane_mask, int format)
414 {
415 }
416
417 unsigned long
418 XGetPixel (XImage *ximage, int x, int y)
419 {
420 }
421
422 int
423 XSetForeground (Display *dpy, GC gc, unsigned long fg)
424 {
425 }
426
427 int
428 XTextExtents16 (XFontStruct *f, const XChar2b *s, int length,
429                 int *dir_ret, int *ascent_ret, int *descent_ret,
430                 XCharStruct *cs)
431 {
432 }