Don't fetch delay over and over ... do it once, and stash the result in state.
[unicode-screensaver.git] / unicode.c
1 /* unicode (c) 2006,2009
2  * Joachim Breitner <mail@joachim-breitner.de>
3  *
4  * Permission to use, copy, modify, distribute, and sell this software and its
5  * documentation for any purpose is hereby granted without fee, provided that
6  * the above copyright notice appear in all copies and that both that
7  * copyright notice and this permission notice appear in supporting
8  * documentation.  No representations are made about the suitability of this
9  * software for any purpose.  It is provided "as is" without express or 
10  * implied warranty.
11  *
12  */
13
14 #include <X11/Xft/Xft.h>
15
16 #include "unicode-names.h"
17 #include "screenhack.h"
18
19 #define NUM_FONTS 2
20
21
22 struct unicode_state {
23         Bool blank;
24
25         XftFont*        fonts[NUM_FONTS];
26         XftFont*        tfont;
27         XftDraw*        draw;
28         XftColor        font_color;
29         XColor          bg_color;
30         unsigned        delay;
31 };
32
33 static void *
34 unicode_init (Display *dpy, Window window)
35 {
36         struct unicode_state *state = malloc(sizeof(struct unicode_state));
37         Colormap cmap;
38         XWindowAttributes xgwa;
39         XColor color;
40         XRenderColor font_color;
41
42         XGetWindowAttributes (dpy, window, &xgwa);
43         state->blank = True;
44
45         cmap = xgwa.colormap;
46
47         state->fonts[0] = XftFontOpen(dpy, 0,
48                 XFT_FAMILY,  XftTypeString, "Open Symbol",
49                 XFT_PIXEL_SIZE, XftTypeInteger, xgwa.height-100,
50                 NULL
51                 );
52         state->fonts[1] = XftFontOpen(dpy, 0,
53                 XFT_FAMILY,  XftTypeString, "FreeSans",
54                 XFT_PIXEL_SIZE, XftTypeInteger, xgwa.height-100,
55                 NULL
56                 );
57         state->tfont = XftFontOpen(dpy, 0,
58                 XFT_FAMILY,  XftTypeString, "FreeSans",
59                 XFT_PIXEL_SIZE, XftTypeInteger, 40,
60                 NULL
61                 );
62
63         state->draw = XftDrawCreate(dpy, window, xgwa.visual, cmap); 
64         state->bg_color.pixel = get_pixel_resource(dpy, cmap, "background", "Background");
65         XQueryColor(dpy, cmap, &state->bg_color);
66
67         color.pixel = get_pixel_resource(dpy, cmap, "foreground", "Foreground");
68         XQueryColor(dpy, cmap, &color);
69
70         state->delay = get_seconds_resource(dpy, "delay", "Delay")*1000*1000;
71         font_color.red = color.red;
72         font_color.green = color.green;
73         font_color.blue = color.blue;
74         font_color.alpha = 0xFFFF;
75
76         XftColorAllocValue(dpy, xgwa.visual, cmap, &font_color, &state->font_color);
77         XSetWindowBackground(dpy, window, state->bg_color.pixel);
78         XClearWindow (dpy, window);
79
80         return state;
81 }
82
83 static unsigned long
84 unicode_draw (Display *dpy, Window win, void *void_state) {
85         XGlyphInfo      extents;
86         FcChar32        pick;
87         char            name[100];
88         int             font;
89         int             i;
90         struct unicode_state *state = (struct unicode_state *)void_state;
91         unsigned long unicode_names_length
92                 = (sizeof(unicode_names)/sizeof(unicode_names[0]));
93         const UnicodeName* nameEntry;
94
95         if (state->blank) {
96                 XWindowAttributes xgwa;
97                 XGetWindowAttributes (dpy, win, &xgwa);
98
99                 /* Find a unicode character that is contained in one of the fonts
100                    We try 100 random points before sleeping, to avoid an endless cycle */
101                 for (i = 0; i < 100; i++) {
102                         nameEntry = &unicode_names[random() % unicode_names_length];
103                         pick = nameEntry->index;
104                         /* printf("Trying U+%04X\n", pick); */
105
106                         for (font = 0; font < NUM_FONTS; font++) {
107                                 if (XftCharExists (dpy, state->fonts[font], pick)) break;
108                         }
109                         if (font < NUM_FONTS) break;
110                 }
111                 if (i == 100) return (1000*1000);
112
113                 /* printf("Picked font %d, U+%04X\n", font, pick); */
114                 sprintf(name,"U+%04X: ", pick);
115                 strcat(name, unicode_name_get_name(nameEntry));
116
117                 XftTextExtents32(dpy,state->fonts[font],&pick,1,&extents); 
118                 XftDrawString32(state->draw,&state->font_color,state->fonts[font],
119                         xgwa.width/2  - extents.width/2  + extents.x,
120                         xgwa.height/2 - extents.height/2 + extents.y,
121                         &pick,1); 
122
123                 XftDrawStringUtf8(state->draw,&state->font_color,state->tfont,
124                         5,
125                         xgwa.height - 5,
126                         (unsigned char *)name,strlen(name)); 
127                 XSync (dpy, False);
128
129                 state->blank = False;
130                 return (state->delay);
131         } else {
132                 XClearWindow (dpy, win);
133                 XSync (dpy, False);
134                 state->blank = True;
135                 return (1000*1000);
136         }
137
138 }
139
140 static void
141 unicode_reshape (Display *dpy, Window window, void *state,
142                  unsigned int width, unsigned int height) {
143 }               
144
145 static Bool
146 unicode_event (Display *dpy, Window window, void *state,
147                  XEvent *event) {
148                  return False;
149 }               
150
151 static void
152 unicode_free (Display *dpy, Window window, void *state) {
153 }               
154
155
156 char *progclass = "Unicode";
157
158 static char const *unicode_defaults [] = {
159   ".background: white",
160   ".foreground: black",
161   "*delay:      7",
162   0
163 };
164
165 static XrmOptionDescRec unicode_options [] = {
166   { "-delay",           ".delay",               XrmoptionSepArg, 0 },
167   { "-foreground",      ".foreground",          XrmoptionSepArg, 0 },
168   { "-background",      ".background",          XrmoptionSepArg, 0 },
169   { 0, 0, 0, 0 }
170 };
171
172 XSCREENSAVER_MODULE("Unicode",unicode)