1 /* gltext, Copyright (c) 2001 Jamie Zawinski <jwz@jwz.org>
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
12 #include <X11/Intrinsic.h>
14 extern XtAppContext app;
16 #define PROGCLASS "GLText"
17 #define HACK_INIT init_text
18 #define HACK_DRAW draw_text
19 #define HACK_RESHAPE reshape_text
20 #define sws_opts xlockmore_opts
22 #define DEF_TEXT "(default)"
24 #define DEFAULTS "*delay: 10000 \n" \
25 "*showFPS: False \n" \
26 "*wireframe: False \n" \
27 "*text: " DEF_TEXT "\n"
30 #define countof(x) (sizeof((x))/sizeof((*x)))
32 #include "xlockmore.h"
35 #ifdef USE_GL /* whole file */
38 # include <sys/utsname.h>
39 #endif /* HAVE_UNAME */
43 #include "glutstroke.h"
44 #include "glut_roman.h"
45 #define GLUT_FONT (&glutStrokeRoman)
49 GLXContext *glx_context;
51 GLfloat rotx, roty, rotz; /* current object rotation */
52 GLfloat dx, dy, dz; /* current rotational velocity */
53 GLfloat ddx, ddy, ddz; /* current rotational acceleration */
54 GLfloat d_max; /* max velocity */
64 static text_configuration *tps = NULL;
68 static XrmOptionDescRec opts[] = {
69 { "-text", ".text", XrmoptionSepArg, 0 }
72 static argtype vars[] = {
73 {(caddr_t *) &text, "text", "Text", DEF_TEXT, t_String},
76 ModeSpecOpt sws_opts = {countof(opts), opts, countof(vars), vars, NULL};
79 /* Window management, etc
82 reshape_text (ModeInfo *mi, int width, int height)
84 GLfloat h = (GLfloat) height / (GLfloat) width;
86 glViewport (0, 0, (GLint) width, (GLint) height);
88 glMatrixMode(GL_PROJECTION);
91 gluPerspective( 30.0, 1/h, 1.0, 100.0 );
92 gluLookAt( 0.0, 0.0, 15.0,
95 glMatrixMode(GL_MODELVIEW);
97 glTranslatef(0.0, 0.0, -15.0);
99 glClear(GL_COLOR_BUFFER_BIT);
104 gl_init (ModeInfo *mi)
106 text_configuration *tp = &tps[MI_SCREEN(mi)];
107 int wire = MI_IS_WIREFRAME(mi);
109 static GLfloat pos[4] = {5.0, 5.0, 10.0, 1.0};
113 glLightfv(GL_LIGHT0, GL_POSITION, pos);
114 glEnable(GL_CULL_FACE);
115 glEnable(GL_LIGHTING);
117 glEnable(GL_DEPTH_TEST);
120 tp->text_list = glGenLists (1);
121 glNewList (tp->text_list, GL_COMPILE);
126 /* lifted from lament.c */
127 #define RAND(n) ((long) ((random() & 0x7fffffff) % ((long) (n))))
128 #define RANDSIGN() ((random() & 1) ? 1 : -1)
131 rotate(GLfloat *pos, GLfloat *v, GLfloat *dv, GLfloat max_v)
146 if (ppos < 0) abort();
147 if (ppos > 1.0) abort();
148 *pos = (*pos > 0 ? ppos : -ppos);
154 if (*v > max_v || *v < -max_v)
158 /* If it stops, start it going in the other direction. */
165 /* keep going in the same direction */
180 /* Alter direction of rotational acceleration randomly. */
181 if (! (random() % 120))
184 /* Change acceleration very occasionally. */
185 if (! (random() % 200))
189 else if (random() & 1)
198 init_text (ModeInfo *mi)
200 text_configuration *tp;
203 tps = (text_configuration *)
204 calloc (MI_NUM_SCREENS(mi), sizeof (text_configuration));
206 fprintf(stderr, "%s: out of memory\n", progname);
210 tp = &tps[MI_SCREEN(mi)];
213 tp = &tps[MI_SCREEN(mi)];
215 if ((tp->glx_context = init_GL(mi)) != NULL) {
217 reshape_text (mi, MI_WIDTH(mi), MI_HEIGHT(mi));
220 tp->rotx = frand(1.0) * RANDSIGN();
221 tp->roty = frand(1.0) * RANDSIGN();
222 tp->rotz = frand(1.0) * RANDSIGN();
224 /* bell curve from 0-6 degrees, avg 3 */
225 tp->dx = (frand(1) + frand(1) + frand(1)) / (360/2);
226 tp->dy = (frand(1) + frand(1) + frand(1)) / (360/2);
227 tp->dz = (frand(1) + frand(1) + frand(1)) / (360/2);
229 tp->d_max = tp->dx * 2;
231 tp->ddx = 0.00006 + frand(0.00003);
232 tp->ddy = 0.00006 + frand(0.00003);
233 tp->ddz = 0.00006 + frand(0.00003);
239 if (!text || !*text || !strcmp(text, "(default)"))
244 if (uname (&uts) < 0)
246 text = strdup("uname() failed");
251 if ((s = strchr(uts.nodename, '.')))
253 text = (char *) malloc(strlen(uts.nodename) +
254 strlen(uts.sysname) +
255 strlen(uts.version) +
256 strlen(uts.release) + 10);
258 sprintf(text, "%s\n%s %s.%s",
259 uts.nodename, uts.sysname, uts.version, uts.release);
261 sprintf(text, "%s\n%s %s",
262 uts.nodename, uts.sysname, uts.release);
265 # else /* !HAVE_UNAME */
267 text = strdup(getenv("SYS$NODE"));
269 text = strdup("* *\n* * *\nxscreensaver\n* * *\n* *");
271 # endif /* !HAVE_UNAME */
276 tp->colors = (XColor *) calloc(tp->ncolors, sizeof(XColor));
277 make_smooth_colormap (0, 0, 0,
278 tp->colors, &tp->ncolors,
284 unit_tube (Bool wire)
292 glShadeModel(GL_SMOOTH);
296 for (i = 0; i < 8; i++)
299 glBegin(wire ? GL_LINE_LOOP : GL_QUADS);
300 glVertex3f(0.5, 0.0, -d3); glVertex3f(0.5, 1.0, -d3);
301 glVertex3f(0.5, 1.0, d3); glVertex3f(0.5, 0.0, d3);
303 glRotatef(45, 0, 1, 0);
308 glNormal3f(0, -1, 0);
309 glBegin(GL_TRIANGLE_FAN);
311 glVertex3f(-d3, 0, -0.5); glVertex3f( d3, 0, -0.5);
312 glVertex3f( 0.5, 0, -d3); glVertex3f( 0.5, 0, d3);
313 glVertex3f( d3, 0, 0.5); glVertex3f(-d3, 0, 0.5);
314 glVertex3f(-0.5, 0, d3); glVertex3f(-0.5, 0, -d3);
315 glVertex3f(-d3, 0, -0.5); glVertex3f( d3, 0, -0.5);
319 glTranslatef(0, 1, 0);
322 glBegin(GL_TRIANGLE_FAN);
324 glVertex3f(-0.5, 0, -d3); glVertex3f(-0.5, 0, d3);
325 glVertex3f(-d3, 0, 0.5); glVertex3f( d3, 0, 0.5);
326 glVertex3f( 0.5, 0, d3); glVertex3f( 0.5, 0, -d3);
327 glVertex3f( d3, 0, -0.5); glVertex3f(-d3, 0, -0.5);
328 glVertex3f(-0.5, 0, -d3); glVertex3f(-0.5, 0, d3);
337 tube (GLfloat x1, GLfloat y1,
338 GLfloat x2, GLfloat y2,
345 if (y1 == y2) y2 += 0.01; /* waah... */
347 length = sqrt(((x2-x1)*(x2-x1)) +
350 rot = (acos((x2-x1)/length)
353 if (rot < 0 || rot > 180) abort();
354 if (y1 <= y2) rot = -rot;
358 if (diameter < 0) abort();
359 if (length < 0) abort();
363 glTranslatef(x1, y1, z);
364 glRotatef(rot+90, 0, 0, 1);
365 glTranslatef(0, -diameter/8, 0);
366 glScalef (diameter, length+diameter/4, diameter);
375 fill_character (GLUTstrokeFont font, int c, Bool wire)
379 const StrokeCharRec *ch;
380 const StrokeRec *stroke;
381 const CoordRec *coord;
382 StrokeFontPtr fontinfo;
385 fontinfo = (StrokeFontPtr) font;
387 if (c < 0 || c >= fontinfo->num_chars)
389 ch = &(fontinfo->ch[c]);
393 for (i = ch->num_strokes, stroke = ch->stroke;
394 i > 0; i--, stroke++) {
395 for (j = stroke->num_coords, coord = stroke->coord;
398 if (j != stroke->num_coords)
399 tube (lx, ly, coord->x, coord->y, 0, tube_width, wire);
404 return (int) (ch->right + tube_width/2);
411 text_extents (const char *string, int *wP, int *hP)
413 const char *s, *start;
414 int line_height = GLUT_FONT->top - GLUT_FONT->bottom;
421 if (*s == '\n' || *s == 0)
426 w += glutStrokeWidth(GLUT_FONT, *start);
431 if (w > *wP) *wP = w;
445 fill_string (const char *string, Bool wire)
447 const char *s, *start;
448 int line_height = GLUT_FONT->top - GLUT_FONT->bottom;
450 GLfloat x = 0, y = 0;
454 lines = text_extents (string, &ow, &oh);
456 y = oh / 2 - line_height;
461 if (*s == '\n' || *s == 0)
466 for (s2 = start; s2 < s; s2++)
467 line_w += glutStrokeWidth (GLUT_FONT, *s2);
469 x = (-ow/2) + ((ow-line_w)/2);
473 glTranslatef(x, y, 0);
474 off = fill_character (GLUT_FONT, *start, wire);
491 draw_text (ModeInfo *mi)
493 text_configuration *tp = &tps[MI_SCREEN(mi)];
494 Display *dpy = MI_DISPLAY(mi);
495 Window window = MI_WINDOW(mi);
496 int wire = MI_IS_WIREFRAME(mi);
498 static GLfloat color[4] = {0.0, 0.0, 0.0, 1.0};
499 static GLfloat white[4] = {1.0, 1.0, 1.0, 1.0};
501 if (!tp->glx_context)
504 glShadeModel(GL_SMOOTH);
506 glEnable(GL_DEPTH_TEST);
507 glEnable(GL_NORMALIZE);
508 glEnable(GL_CULL_FACE);
510 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
514 glScalef(1.1, 1.1, 1.1);
517 static int frame = 0;
520 # define SINOID(SCALE,SIZE) \
521 ((((1 + sin((frame * (SCALE)) / 2 * M_PI)) / 2.0) * (SIZE)) - (SIZE)/2)
522 x = SINOID(0.031, 9.0);
523 y = SINOID(0.023, 9.0);
524 z = SINOID(0.017, 9.0);
526 glTranslatef(x, y, z);
531 if (x < 0) x = 1 - (x + 1);
532 if (y < 0) y = 1 - (y + 1);
533 if (z < 0) z = 1 - (z + 1);
535 glRotatef(x * 360, 1.0, 0.0, 0.0);
536 glRotatef(y * 360, 0.0, 1.0, 0.0);
537 glRotatef(z * 360, 0.0, 0.0, 1.0);
539 rotate(&tp->rotx, &tp->dx, &tp->ddx, tp->d_max);
540 rotate(&tp->roty, &tp->dy, &tp->ddy, tp->d_max);
541 rotate(&tp->rotz, &tp->dz, &tp->ddz, tp->d_max);
546 color[0] = tp->colors[tp->ccolor].red / 65536.0;
547 color[1] = tp->colors[tp->ccolor].green / 65536.0;
548 color[2] = tp->colors[tp->ccolor].blue / 65536.0;
550 if (tp->ccolor >= tp->ncolors) tp->ccolor = 0;
552 glMaterialfv (GL_FRONT, GL_AMBIENT_AND_DIFFUSE, color);
554 glScalef(0.01, 0.01, 0.01);
555 fill_string(text, wire);
559 if (mi->fps_p) do_fps (mi);
562 glXSwapBuffers(dpy, window);