From d3a98cf6cbc3bd0b9efc570f58e8812c03931c18 Mon Sep 17 00:00:00 2001 From: Simon Rettberg Date: Tue, 16 Oct 2018 10:08:48 +0200 Subject: Original 5.40 --- hacks/glx/fliptext.c | 1001 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 1001 insertions(+) create mode 100644 hacks/glx/fliptext.c (limited to 'hacks/glx/fliptext.c') diff --git a/hacks/glx/fliptext.c b/hacks/glx/fliptext.c new file mode 100644 index 0000000..c233e8b --- /dev/null +++ b/hacks/glx/fliptext.c @@ -0,0 +1,1001 @@ +/* + * fliptext, Copyright (c) 2005-2015 Jamie Zawinski + * + * Permission to use, copy, modify, distribute, and sell this software and its + * documentation for any purpose is hereby granted without fee, provided that + * the above copyright notice appear in all copies and that both that + * copyright notice and this permission notice appear in supporting + * documentation. No representations are made about the suitability of this + * software for any purpose. It is provided "as is" without express or + * implied warranty. + */ + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif /* HAVE_CONFIG_H */ + +#define DEF_FONT "-*-utopia-bold-r-normal-*-*-720-*-*-*-*-*-*" +#define DEF_COLOR "#00CCFF" + +#define DEFAULTS "*delay: 10000 \n" \ + "*showFPS: False \n" \ + "*wireframe: False \n" \ + "*usePty: False \n" \ + "*texFontCacheSize: 60 \n" \ + "*font: " DEF_FONT "\n" \ + ".foreground: " DEF_COLOR "\n" \ + "*program: xscreensaver-text --cols 0" /* don't wrap */ + +# define release_fliptext 0 +# define fliptext_handle_event xlockmore_no_events +#undef countof +#define countof(x) (sizeof((x))/sizeof((*x))) + +#undef BELLRAND +#define BELLRAND(n) ((frand((n)) + frand((n)) + frand((n))) / 3) + +#include "xlockmore.h" +#include "texfont.h" +#include "textclient.h" + +#ifdef USE_GL /* whole file */ + +/* Should be in */ +# ifndef GL_TEXTURE_MAX_ANISOTROPY_EXT +# define GL_TEXTURE_MAX_ANISOTROPY_EXT 0x84FE +# endif +# ifndef GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT +# define GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT 0x84FF +# endif + + +#define DEF_LINES "8" +#define DEF_FONT_SIZE "20" +#define DEF_COLUMNS "80" +#define DEF_ALIGNMENT "random" +#define DEF_SPEED "1.0" +#define TAB_WIDTH 8 + +#define FONT_WEIGHT 14 +#define KEEP_ASPECT + +typedef enum { NEW, HESITATE, IN, LINGER, OUT, DEAD } line_state; +typedef enum { SCROLL_BOTTOM, SCROLL_TOP, SPIN } line_anim_type; + +typedef struct { GLfloat x, y, z; } XYZ; + +typedef struct { + char *text; + GLfloat width, height; /* size */ + XYZ from, to, current; /* start, end, and current position */ + GLfloat fth, tth, cth; /* rotation around Z */ + + int cluster_size; /* how many lines in this cluster */ + int cluster_pos; /* position of this line in the cluster */ + + line_state state; /* current motion model */ + int step, steps; /* progress along this path */ + GLfloat color[4]; + +} line; + + +typedef struct { + Display *dpy; + GLXContext *glx_context; + + texture_font_data *texfont; + text_data *tc; + + int alignment; + + char *buf; + int buf_size; + int buf_tail; + + int char_width; /* in font units */ + int line_height; /* in font units */ + double font_scale; /* convert font units to display units */ + + int font_wrap_pixels; /* in font units (for wrapping text) */ + + int top_margin, bottom_margin; + int left_margin, right_margin; + + int nlines; + int lines_size; + line **lines; + + line_anim_type anim_type; + XYZ in, mid, out; + XYZ rotation; + GLfloat color[4]; + +} fliptext_configuration; + + +static fliptext_configuration *scs = NULL; + +static int max_lines, min_lines; +static float font_size; +static int target_columns; +static char *alignment_str; +static int alignment_random_p; +static GLfloat speed; + +static XrmOptionDescRec opts[] = { + {"-lines", ".lines", XrmoptionSepArg, 0 }, + {"-size", ".fontSize", XrmoptionSepArg, 0 }, + {"-columns", ".columns", XrmoptionSepArg, 0 }, + {"-speed", ".speed", XrmoptionSepArg, 0 }, +/*{"-font", ".font", XrmoptionSepArg, 0 },*/ + {"-alignment", ".alignment", XrmoptionSepArg, 0 }, + {"-left", ".alignment", XrmoptionNoArg, "Left" }, + {"-right", ".alignment", XrmoptionNoArg, "Right" }, + {"-center", ".alignment", XrmoptionNoArg, "Center" }, +}; + +static argtype vars[] = { + {&max_lines, "lines", "Integer", DEF_LINES, t_Int}, + {&font_size, "fontSize", "Float", DEF_FONT_SIZE, t_Float}, + {&target_columns, "columns", "Integer", DEF_COLUMNS, t_Int}, + {&alignment_str, "alignment", "Alignment", DEF_ALIGNMENT, t_String}, + {&speed, "speed", "Speed", DEF_SPEED, t_Float}, +}; + +ENTRYPOINT ModeSpecOpt fliptext_opts = {countof(opts), opts, countof(vars), vars, NULL}; + + + +/* Tabs are bad, mmmkay? */ + +static char * +untabify (const char *string) +{ + const char *ostring = string; + char *result = (char *) malloc ((strlen(string) * 8) + 1); + char *out = result; + int col = 0; + while (*string) + { + if (*string == '\t') + { + do { + col++; + *out++ = ' '; + } while (col % TAB_WIDTH); + string++; + } + else if (*string == '\r' || *string == '\n') + { + *out++ = *string++; + col = 0; + } + else if (*string == '\010') /* backspace */ + { + if (string > ostring) + out--, string++; + } + else + { + *out++ = *string++; + col++; + } + } + *out = 0; + + return result; +} + +static void +strip (char *s, Bool leading, Bool trailing) +{ + int L = strlen(s); + if (trailing) + while (L > 0 && (s[L-1] == ' ' || s[L-1] == '\t')) + s[L--] = 0; + if (leading) + { + char *s2 = s; + while (*s2 == ' ' || *s2 == '\t') + s2++; + if (s == s2) + return; + while (*s2) + *s++ = *s2++; + *s = 0; + } +} + + +static int +char_width (fliptext_configuration *sc, char c) +{ + XCharStruct e; + char s[2]; + s[0] = c; + s[1] = 0; + texture_string_metrics (sc->texfont, s, &e, 0, 0); + return e.width; +} + + +/* Returns a single line of text from the output buffer of the subprocess, + taking into account wrapping, centering, etc. Returns 0 if no complete + line is currently available. + */ +static char * +get_one_line (fliptext_configuration *sc) +{ + char *result = 0; + int wrap_pix = sc->font_wrap_pixels; + int col = 0; + int col_pix = 0; + char *s = sc->buf; + int target = sc->buf_size - sc->buf_tail - 2; + + /* Fill as much as we can into sc->buf, but stop at newline. + */ + while (target > 0) + { + int c = textclient_getc (sc->tc); + if (c <= 0) + break; + sc->buf[sc->buf_tail++] = (char) c; + sc->buf[sc->buf_tail] = 0; + target--; + if (c == '\r' || c == '\n') + break; + } + + while (!result) + { + int cw; + + if (s >= sc->buf + sc->buf_tail) + /* Reached end of buffer before end of line. Bail. */ + return 0; + + cw = char_width (sc, *s); + + if (*s == '\r' || *s == '\n' || + col_pix + cw >= wrap_pix) + { + int L = s - sc->buf; + + if (*s == '\r' || *s == '\n') + { + if (*s == '\r' && s[1] == '\n') /* swallow CRLF too */ + *s++ = 0; + + *s++ = 0; + } + else + { + /* We wrapped -- try to back up to the previous word boundary. */ + char *s2 = s; + int n = 0; + while (s2 > sc->buf && *s2 != ' ' && *s2 != '\t') + s2--, n++; + if (s2 > sc->buf) + { + s = s2; + *s++ = 0; + L = s - sc->buf; + } + } + + if (result) abort(); + result = (char *) malloc (L+1); + memcpy (result, sc->buf, L); + result[L] = 0; + + { + char *t = result; + char *ut = untabify (t); + strip (ut, (sc->alignment == 0), 1); /* if centering, strip + leading whitespace too */ + result = ut; + free (t); + } + + if (sc->buf_tail > (s - sc->buf)) + { + int i = sc->buf_tail - (s - sc->buf); + memmove (sc->buf, s, i); + sc->buf_tail = i; + sc->buf[sc->buf_tail] = 0; + } + else + { + sc->buf_tail = 0; + } + + sc->buf[sc->buf_tail] = 0; + s = sc->buf; + col = 0; + col_pix = 0; + } + else + { + col++; + col_pix += cw; + if (*s == '\t') + { + int tab_pix = TAB_WIDTH * sc->char_width; + col = TAB_WIDTH * ((col / TAB_WIDTH) + 1); + col_pix = tab_pix * ((col / tab_pix) + 1); + } + s++; + } + } + + return result; +} + + +static Bool +blank_p (const char *s) +{ + for (; *s; s++) + if (*s != ' ' && *s != '\t' && *s != '\r' && *s != '\n') + return False; + return True; +} + +/* Reads some text from the subprocess, and creates and returns a `line' + object. Adds that object to the lines list. Returns 0 if no text + available yet. + + If skip_blanks_p, then keep trying for new lines of text until we + get one that is not empty. + */ +static line * +make_line (fliptext_configuration *sc, Bool skip_blanks_p) +{ + XCharStruct e; + line *ln; + char *s; + + AGAIN: + s = get_one_line (sc); + if (s && skip_blanks_p && blank_p (s)) + { + free (s); + goto AGAIN; + } + + if (!s) return 0; + + ln = (line *) calloc (1, sizeof(*ln)); + ln->text = s; + ln->state = NEW; + texture_string_metrics (sc->texfont, s, &e, 0, 0); + ln->width = sc->font_scale * e.width; + ln->height = sc->font_scale * sc->line_height; + + memcpy (ln->color, sc->color, sizeof(ln->color)); + + sc->nlines++; + if (sc->lines_size <= sc->nlines) + { + sc->lines_size = (sc->lines_size * 1.2) + sc->nlines; + sc->lines = (line **) + realloc (sc->lines, sc->lines_size * sizeof(*sc->lines)); + if (! sc->lines) + { + fprintf (stderr, "%s: out of memory (%d lines)\n", + progname, sc->lines_size); + exit (1); + } + } + + sc->lines[sc->nlines-1] = ln; + return ln; +} + + +/* frees the object and removes it from the list. + */ +static void +free_line (fliptext_configuration *sc, line *line) +{ + int i; + for (i = 0; i < sc->nlines; i++) + if (sc->lines[i] == line) + break; + if (i == sc->nlines) abort(); + for (; i < sc->nlines-1; i++) + sc->lines[i] = sc->lines[i+1]; + sc->lines[i] = 0; + sc->nlines--; + + free (line->text); + free (line); +} + + +static void +draw_line (ModeInfo *mi, line *line) +{ + int wire = MI_IS_WIREFRAME(mi); + fliptext_configuration *sc = &scs[MI_SCREEN(mi)]; + + if (! line->text || !*line->text || + line->state == NEW || line->state == HESITATE || line->state == DEAD) + return; + + glPushMatrix(); + glTranslatef (line->current.x, line->current.y, line->current.z); + + glRotatef (line->cth, 0, 1, 0); + + if (sc->alignment == 1) + glTranslatef (-line->width, 0, 0); + else if (sc->alignment == 0) + glTranslatef (-line->width/2, 0, 0); + + glScalef (sc->font_scale, sc->font_scale, sc->font_scale); + + glColor4f (line->color[0], line->color[1], line->color[2], line->color[3]); + + if (!wire) + print_texture_string (sc->texfont, line->text); + else + { + int w, h; + char *s = line->text; + char c[2]; + c[1]=0; + glDisable (GL_TEXTURE_2D); + glColor3f (0.4, 0.4, 0.4); + while (*s) + { + XCharStruct e; + *c = *s++; + texture_string_metrics (sc->texfont, c, &e, 0, 0); + w = e.width; + h = e.ascent + e.descent; + glBegin (GL_LINE_LOOP); + glVertex3f (0, 0, 0); + glVertex3f (w, 0, 0); + glVertex3f (w, h, 0); + glVertex3f (0, h, 0); + glEnd(); + glTranslatef (w, 0, 0); + } + } + +#if 0 + glDisable (GL_TEXTURE_2D); + glColor3f (0.4, 0.4, 0.4); + glBegin (GL_LINE_LOOP); + glVertex3f (0, 0, 0); + glVertex3f (line->width/sc->font_scale, 0, 0); + glVertex3f (line->width/sc->font_scale, line->height/sc->font_scale, 0); + glVertex3f (0, line->height/sc->font_scale, 0); + glEnd(); + if (!wire) glEnable (GL_TEXTURE_2D); +#endif + + glPopMatrix(); + + mi->polygon_count += strlen (line->text); +} + +static void +tick_line (fliptext_configuration *sc, line *line) +{ + int stagger = 30; /* frames of delay between line spin-outs */ + int slide = 600; /* frames in a slide in/out */ + int linger = 0; /* frames to pause with no motion */ + double i, ii; + + if (line->state >= DEAD) abort(); + if (++line->step >= line->steps) + { + line->state++; + line->step = 0; + + if (linger == 0 && line->state == LINGER) + line->state++; + + if (sc->anim_type != SPIN) + stagger *= 2; + + switch (line->state) + { + case HESITATE: /* entering state HESITATE */ + switch (sc->anim_type) + { + case SPIN: + line->steps = (line->cluster_pos * stagger); + break; + case SCROLL_TOP: + line->steps = stagger * (line->cluster_size - line->cluster_pos); + break; + case SCROLL_BOTTOM: + line->steps = stagger * line->cluster_pos; + break; + default: + abort(); + } + break; + + case IN: + line->color[3] = 0; + switch (sc->anim_type) + { + case SCROLL_BOTTOM: /* entering state BOTTOM IN */ + line->from = sc->in; + line->to = sc->mid; + line->from.y = (sc->bottom_margin - + (line->height * + (line->cluster_pos + 1))); + line->to.y += (line->height * + ((line->cluster_size/2.0) - line->cluster_pos)); + line->steps = slide; + break; + + case SCROLL_TOP: /* entering state TOP IN */ + line->from = sc->in; + line->to = sc->mid; + line->from.y = (sc->top_margin + + (line->height * + (line->cluster_size - line->cluster_pos))); + line->to.y += (line->height * + ((line->cluster_size/2.0) - line->cluster_pos)); + line->steps = slide; + break; + + case SPIN: /* entering state SPIN IN */ + line->from = sc->in; + line->to = sc->mid; + line->to.y += (line->height * + ((line->cluster_size/2.0) - line->cluster_pos)); + line->from.y += (line->height * + ((line->cluster_size/2.0) - line->cluster_pos)); + + line->fth = 270; + line->tth = 0; + line->steps = slide; + break; + + default: + abort(); + } + break; + + case OUT: + switch (sc->anim_type) + { + case SCROLL_BOTTOM: /* entering state BOTTOM OUT */ + line->from = line->to; + line->to = sc->out; + line->to.y = (sc->top_margin + + (line->height * + (line->cluster_size - line->cluster_pos))); + line->steps = slide; + break; + + case SCROLL_TOP: /* entering state TOP OUT */ + line->from = line->to; + line->to = sc->out; + line->to.y = (sc->bottom_margin - + (line->height * + (line->cluster_pos + 1))); + line->steps = slide; + break; + + case SPIN: /* entering state SPIN OUT */ + line->from = line->to; + line->to = sc->out; + line->to.y += (line->height * + ((line->cluster_size/2.0) - line->cluster_pos)); + + line->fth = line->tth; + line->tth = -270; + line->steps = slide; + break; + + default: + abort(); + } + break; + + case LINGER: + line->from = line->to; + line->steps = linger; + break; + + default: + break; + } + + line->steps /= speed; + } + + switch (line->state) + { + case IN: + case OUT: + i = (double) line->step / line->steps; + + /* Move along the path exponentially, slow side towards the middle. */ + if (line->state == OUT) + ii = i * i; + else + ii = 1 - ((1-i) * (1-i)); + + line->current.x = line->from.x + (ii * (line->to.x - line->from.x)); + line->current.y = line->from.y + (ii * (line->to.y - line->from.y)); + line->current.z = line->from.z + (ii * (line->to.z - line->from.z)); + line->cth = line->fth + (ii * (line->tth - line->fth)); + + if (line->state == OUT) ii = 1-ii; + line->color[3] = sc->color[3] * ii; + break; + + case HESITATE: + case LINGER: + case DEAD: + break; + default: + abort(); + } +} + + +/* Start a new cluster of lines going. + Pick their anim type, and in, mid, and out positions. + */ +static void +reset_lines (ModeInfo *mi) +{ + fliptext_configuration *sc = &scs[MI_SCREEN(mi)]; + int i; + line *prev = 0; + GLfloat minx, maxx, miny, maxy, minz, maxz, maxw, maxh; + + sc->rotation.x = 5 - BELLRAND(10); + sc->rotation.y = 5 - BELLRAND(10); + sc->rotation.z = 5 - BELLRAND(10); + + switch (random() % 8) + { + case 0: sc->anim_type = SCROLL_TOP; break; + case 1: sc->anim_type = SCROLL_BOTTOM; break; + default: sc->anim_type = SPIN; break; + } + + minx = sc->left_margin * 0.9; + maxx = sc->right_margin * 0.9; + + miny = sc->bottom_margin * 0.9; + maxy = sc->top_margin * 0.9; + + minz = sc->left_margin * 5; + maxz = sc->right_margin * 2; + + maxw = sc->font_wrap_pixels * sc->font_scale; + maxh = max_lines * sc->line_height * sc->font_scale; + + if (maxw > maxx - minx) + maxw = maxx - minx; + if (maxh > maxy - miny) + maxh = maxy - miny; + + if (alignment_random_p) + sc->alignment = (random() % 3) - 1; + + if (sc->alignment == -1) maxx -= maxw; + else if (sc->alignment == 1) minx += maxw; + else minx += maxw/2, maxx -= maxw/2; + + miny += maxh/2; + maxy -= maxh/2; + + sc->mid.x = minx + frand (maxx - minx); + if (sc->anim_type == SPIN) + sc->mid.y = miny + BELLRAND (maxy - miny); + else + sc->mid.y = miny + frand (maxy - miny); + + sc->in.x = BELLRAND(sc->right_margin * 2) - sc->right_margin; + sc->out.x = BELLRAND(sc->right_margin * 2) - sc->right_margin; + + sc->in.y = miny + frand(maxy - miny); + sc->out.y = miny + frand(maxy - miny); + + sc->in.z = minz + frand(maxz - minz); + sc->out.z = minz + frand(maxz - minz); + + sc->mid.z = 0; + + if (sc->anim_type == SPIN && sc->in.z > 0) sc->in.z /= 4; + if (sc->anim_type == SPIN && sc->out.z > 0) sc->out.z /= 4; + + for (i = 0; i < max_lines; i++) + { + line *line = make_line (sc, (i == 0)); + if (!line) break; /* no text available */ + if (i >= min_lines && + (!line->text || !*line->text)) /* blank after min */ + break; + } + + for (i = 0; i < sc->nlines; i++) + { + line *line = sc->lines[i]; + if (!prev) + { + line->from.y = sc->bottom_margin; + line->to.y = 0; + } + else + { + line->from.y = prev->from.y - prev->height; + line->to.y = prev->to.y - prev->height; + } + line->cluster_pos = i; + line->cluster_size = sc->nlines; + prev = line; + } +} + + +static void +parse_color (ModeInfo *mi, const char *name, const char *s, GLfloat *a) +{ + XColor c; + if (! XParseColor (MI_DISPLAY(mi), MI_COLORMAP(mi), s, &c)) + { + fprintf (stderr, "%s: can't parse %s color %s", progname, name, s); + exit (1); + } + a[0] = c.red / 65536.0; + a[1] = c.green / 65536.0; + a[2] = c.blue / 65536.0; + a[3] = 1.0; +} + + +/* Window management, etc + */ +ENTRYPOINT void +reshape_fliptext (ModeInfo *mi, int width, int height) +{ + fliptext_configuration *sc = &scs[MI_SCREEN(mi)]; + GLfloat h = (GLfloat) height / (GLfloat) width; + int y = 0; + + if (width > height * 5) { /* tiny window: show middle */ + height = width * 9/16; + y = -height/2; + h = height / (GLfloat) width; + } + + glViewport (0, y, (GLint) width, (GLint) height); + + glMatrixMode(GL_PROJECTION); + glLoadIdentity(); + gluPerspective (60.0, 1/h, 0.01, 100.0); + + glMatrixMode(GL_MODELVIEW); + glLoadIdentity(); + gluLookAt( 0.0, 0.0, 2.6, + 0.0, 0.0, 0.0, + 0.0, 1.0, 0.0); + + glClear(GL_COLOR_BUFFER_BIT); + + sc->right_margin = sc->top_margin / h; + sc->left_margin = -sc->right_margin; +} + + +ENTRYPOINT void +init_fliptext (ModeInfo *mi) +{ + int wire = MI_IS_WIREFRAME(mi); + + fliptext_configuration *sc; + + MI_INIT(mi, scs); + + sc = &scs[MI_SCREEN(mi)]; + sc->lines = (line **) calloc (max_lines+1, sizeof(char *)); + + sc->dpy = MI_DISPLAY(mi); + + if ((sc->glx_context = init_GL(mi)) != NULL) { + reshape_fliptext (mi, MI_WIDTH(mi), MI_HEIGHT(mi)); + clear_gl_error(); /* WTF? sometimes "invalid op" from glViewport! */ + } + + { + XCharStruct e; + int cw, lh, ascent, descent; + sc->texfont = load_texture_font (MI_DISPLAY(mi), "font"); + check_gl_error ("loading font"); + texture_string_metrics (sc->texfont, "n", &e, &ascent, &descent); + cw = e.width; + lh = ascent + descent; + sc->char_width = cw; + sc->line_height = lh; + } + + if (!wire) + { + glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + glEnable (GL_BLEND); + glEnable (GL_ALPHA_TEST); + glEnable (GL_TEXTURE_2D); + + /* "Anistropic filtering helps for quadrilateral-angled textures. + A sharper image is accomplished by interpolating and filtering + multiple samples from one or more mipmaps to better approximate + very distorted textures. This is the next level of filtering + after trilinear filtering." */ + if (strstr ((char *) glGetString(GL_EXTENSIONS), + "GL_EXT_texture_filter_anisotropic")) + { + GLfloat anisotropic = 0.0; + glGetFloatv (GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT, &anisotropic); + if (anisotropic >= 1.0) + glTexParameterf (GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, + anisotropic); + } + } + + /* The default font is (by fiat) "18 points". + Interpret the user's font size request relative to that. + */ + sc->font_scale = 3 * (font_size / 18.0); + + if (target_columns <= 2) target_columns = 2; + + /* Figure out what the wrap column should be, in font-coordinate pixels. + Compute it from the given -columns value, but don't let it be wider + than the screen. + */ + { + GLfloat maxw = 110 * sc->line_height / sc->font_scale; /* magic... */ + sc->font_wrap_pixels = target_columns * sc->char_width; + if (sc->font_wrap_pixels > maxw || + sc->font_wrap_pixels <= 0) + sc->font_wrap_pixels = maxw; + } + + sc->buf_size = target_columns * max_lines; + sc->buf = (char *) calloc (1, sc->buf_size); + + alignment_random_p = False; + if (!alignment_str || !*alignment_str || + !strcasecmp(alignment_str, "left")) + sc->alignment = -1; + else if (!strcasecmp(alignment_str, "center") || + !strcasecmp(alignment_str, "middle")) + sc->alignment = 0; + else if (!strcasecmp(alignment_str, "right")) + sc->alignment = 1; + else if (!strcasecmp(alignment_str, "random")) + sc->alignment = -1, alignment_random_p = True; + + else + { + fprintf (stderr, + "%s: alignment must be left/center/right/random, not \"%s\"\n", + progname, alignment_str); + exit (1); + } + + sc->tc = textclient_open (sc->dpy); + + if (max_lines < 1) max_lines = 1; + min_lines = max_lines * 0.66; + if (min_lines > max_lines - 3) min_lines = max_lines - 4; + if (min_lines < 1) min_lines = 1; + + parse_color (mi, "foreground", + get_string_resource(mi->dpy, "foreground", "Foreground"), + sc->color); + + sc->top_margin = (sc->char_width * 100); + sc->bottom_margin = -sc->top_margin; + reshape_fliptext (mi, MI_WIDTH(mi), MI_HEIGHT(mi)); /* compute left/right */ +} + + +ENTRYPOINT void +draw_fliptext (ModeInfo *mi) +{ + fliptext_configuration *sc = &scs[MI_SCREEN(mi)]; +/* XtAppContext app = XtDisplayToApplicationContext (sc->dpy);*/ + Display *dpy = MI_DISPLAY(mi); + Window window = MI_WINDOW(mi); + int i; + + if (!sc->glx_context) + return; + + glXMakeCurrent(MI_DISPLAY(mi), MI_WINDOW(mi), *(sc->glx_context)); + +#if 0 + if (XtAppPending (app) & (XtIMTimer|XtIMAlternateInput)) + XtAppProcessEvent (app, XtIMTimer|XtIMAlternateInput); +#endif + + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + + mi->polygon_count = 0; + + glPushMatrix(); + glRotatef(current_device_rotation(), 0, 0, 1); + { + GLfloat s = 3.0 / (sc->top_margin - sc->bottom_margin); + glScalef(s, s, s); + } + + glRotatef (sc->rotation.x, 1, 0, 0); + glRotatef (sc->rotation.y, 0, 1, 0); + glRotatef (sc->rotation.z, 0, 0, 1); + +#if 0 + glDisable (GL_TEXTURE_2D); + glColor3f (1,1,1); + glBegin (GL_LINE_LOOP); + glVertex3f (sc->left_margin, sc->top_margin, 0); + glVertex3f (sc->right_margin, sc->top_margin, 0); + glVertex3f (sc->right_margin, sc->bottom_margin, 0); + glVertex3f (sc->left_margin, sc->bottom_margin, 0); + glEnd(); + glBegin (GL_LINES); + glVertex3f (sc->in.x, sc->top_margin, sc->in.z); + glVertex3f (sc->in.x, sc->bottom_margin, sc->in.z); + glVertex3f (sc->mid.x, sc->top_margin, sc->mid.z); + glVertex3f (sc->mid.x, sc->bottom_margin, sc->mid.z); + glVertex3f (sc->out.x, sc->top_margin, sc->out.z); + glVertex3f (sc->out.x, sc->bottom_margin, sc->out.z); + glEnd(); + glEnable (GL_TEXTURE_2D); +#endif + + for (i = 0; i < sc->nlines; i++) + { + line *line = sc->lines[i]; + draw_line (mi, line); + tick_line (sc, line); + } + + for (i = sc->nlines-1; i >= 0; i--) + { + line *line = sc->lines[i]; + if (line->state == DEAD) + free_line (sc, line); + } + + if (sc->nlines == 0) + reset_lines (mi); + + glPopMatrix(); + + if (mi->fps_p) do_fps (mi); + glFinish(); + glXSwapBuffers(dpy, window); +} + +ENTRYPOINT void +free_fliptext (ModeInfo *mi) +{ + fliptext_configuration *sc = &scs[MI_SCREEN(mi)]; + if (sc->tc) + textclient_close (sc->tc); + free(sc->lines); + + /* #### there's more to free here */ +} + +XSCREENSAVER_MODULE ("FlipText", fliptext) + +#endif /* USE_GL */ -- cgit v1.2.3-55-g7522