1 /* -*- Mode: C; tab-width: 4 -*- */
2 /* text3d --- Shows moving 3D texts */
3
4 #if !defined( lint ) && !defined( SABER )
5 static const char sccsid[] = "@(#)text3d.cc 5.02 2001/11/09 xlockmore";
6
7 #endif
8
9 /* Copyright (c) E. Lassauge, 1998. */
10
11 /*
12 * Permission to use, copy, modify, and distribute this software and its
13 * documentation for any purpose and without fee is hereby granted,
14 * provided that the above copyright notice appear in all copies and that
15 * both that copyright notice and this permission notice appear in
16 * supporting documentation.
17 *
18 * This file is provided AS IS with no warranties of any kind. The author
19 * shall have no liability with respect to the infringement of copyrights,
20 * trade secrets or any patents by this file or any part thereof. In no
21 * event will the author be liable for any lost revenue or profits or
22 * other special, indirect and consequential damages.
23 *
24 * This module is based on a demo of the gltt graphics library
25 * Copyright (C) 1998 Stephane Rehel.
26 *
27 * See the gltt Official Site at http://gltt.sourceforge.net/
28 * May have better luck at http://lassauge.free.fr/xlock/
29 *
30 * My e-mail address changed to <lassauge AT users.sourceforge.net>
31 * Web site at http://lassauge.free.fr/
32 *
33 * Eric Lassauge (October-28-1999)
34 *
35 * Revision History:
36 * 09-Nov-2001: Removed BLANK and various cleanups
37 * Added Wander animation
38 * 09-Mar-2001: Removed an erroneous PushMatrix !!!
39 * 01-Nov-2000: Allocation checks
40 * 28-Oct-1999: fixes from Jouk "I play with every mode" Jansen.
41 * Option ttanimate added.
42 * 02-Jun-1999: patches for initialization errors of GLTT library.
43 * Thanks to Jouk Jansen and Scott <mcmillan@cambridge.com>.
44 * text3d updates for fortunes thanks to Jouk Jansen
45 * <joukj AT hrem.nano.tudelft.nl>
46 * Option no_split added.
47 * 23-Aug-1998: add better handling of "faulty" fontfile and randomize
48 * fontfile if '-ttfont' value is a directory.
49 * Minor changes for AIX from Jouk Jansen
50 * (joukj AT hrem.nano.tudelft.nl).
51 *
52 * TODO :
53 * Need more animation functions. Help welcome !!
54 * Light problem with some letters (don't know why they "reflect" more):
55 * is the problem in gltt or Mesa ???
56 * SPEED !!!!
57 * It may sigfault when compiled with -fschedule-insns2
58 * (i686-pc-linux-gnu)
59 *
60 */
61
62 #ifdef STANDALONE /* xscreensaver mode: can't work ! */
63 #define MODE_text3d
64 #define DEFAULTS "*delay: 100000 \n"
65
66 /* "*ncolors: 64 \n" \
67 "*font: arial.ttf \n" \
68 "*text:X-Window System \n"
69
70 "*filename: \n" \
71 "*fortunefile: \n" \
72 "*program: \n"*/
73
74 #define free_text3d 0
75 #define text3d_handle_event 0
76 extern "C"
77 {
78 #include "xlockmore.h" /* from the xscreensaver distribution */
79 /*#include "iostuff.h"*/
80 }
81 #else /* !STANDALONE */
82 #include "xlock.h" /* from the xlockmore distribution */
83 #include "visgl.h"
84 #ifdef HAS_MMOV
85 #undef error
86 #endif
87 #include "iostuff.h"
88 #endif /* !STANDALONE */
89
90 #ifdef MODE_text3d
91
92 #include <gltt/FTEngine.h>
93 #include <gltt/FTFace.h>
94 #include <gltt/FTInstance.h>
95 #include <gltt/FTGlyph.h>
96 #include <gltt/FTFont.h>
97 #include <gltt/GLTTOutlineFont.h>
98 #include <gltt/GLTTFont.h>
99 #include <gltt/GLTTGlyphPolygonizer.h>
100 #include <gltt/GLTTGlyphTriangulator.h>
101
102 #include "text3d.h"
103 #include <GL/glu.h>
104
105 /* Yes, it's an ugly mix of 'C' and 'C++' functions */
106 #ifndef STANDALONE
107 extern "C" { void init_text3d(ModeInfo * mi); }
108 extern "C" { void draw_text3d(ModeInfo * mi); }
109 extern "C" { void change_text3d(ModeInfo * mi); }
110 extern "C" { void release_text3d(ModeInfo * mi); }
111 extern "C" { void refresh_text3d(ModeInfo * mi); }
112 #endif
113
114 /* arial.ttf is not supplied for legal reasons. */
115 /* NT and Windows 3.1 in C:\WINDOWS\SYSTEM\ARIAL.TTF */
116 /* Windows95 in C:\Windows\Fonts\arial.ttf */
117
118 #ifndef DEF_TTFONT
119 /* Directory of only *.ttf */
120 /* symbol.ttf and wingding.ttf should be excluded or it may core dump */
121 /* can be excluded if gltt is modified see README */
122 #ifdef __CYGWIN__
123 #define DEF_TTFONT "C:\\Windows\\Fonts\\"
124 #else
125 #define DEF_TTFONT "/usr/lib/X11/xlock/fonts/"
126 #endif
127 #endif
128
129 #define DEF_EXTRUSION "25.0"
130 #define DEF_ROTAMPL "1.0"
131 #define DEF_ROTFREQ "0.001"
132 #define DEF_FONTSIZE 220
133 #define DEF_NOSPLIT "False"
134 #define DEF_ANIMATE "Default"
135 static float extrusion;
136 static float rampl;
137 static float rfreq;
138 static char *mode_font;
139 static int nosplit;
140 static char *animate;
141
142 /* Manage Option vars */
143
144 static XrmOptionDescRec opts[] =
145 {
146 {(char *) "-ttfont", (char *) ".text3d.ttfont", XrmoptionSepArg, (caddr_t) NULL},
147 {(char *) "-no_split", (char *) ".text3d.no_split", XrmoptionNoArg, (caddr_t) "on"},
148 {(char *) "+no_split", (char *) ".text3d.no_split", XrmoptionNoArg, (caddr_t) "off"},
149 {(char *) "-extrusion", (char *) ".text3d.extrusion", XrmoptionSepArg, (caddr_t) NULL},
150 {(char *) "-rot_amplitude", (char *) ".text3d.rot_amplitude", XrmoptionSepArg, (caddr_t) NULL},
151 {(char *) "-rot_frequency", (char *) ".text3d.rot_frequency", XrmoptionSepArg, (caddr_t) NULL},
152 {(char *) "-ttanimate", (char *) ".text3d.ttanimate", XrmoptionSepArg, (caddr_t) NULL},
153 };
154
155 static argtype vars[] =
156 {
157 {(void *) & mode_font, (char *) "ttfont", (char *) "TTFont", (char *) DEF_TTFONT, t_String},
158 {(void *) & nosplit, (char *) "no_split", (char *) "NoSplit", (char *) DEF_NOSPLIT, t_Bool},
159 {(void *) & extrusion, (char *) "extrusion", (char *) "Extrusion", (char *) DEF_EXTRUSION, t_Float},
160 {(void *) & rampl, (char *) "rot_amplitude", (char *) "RotationAmplitude", (char *) DEF_ROTAMPL, t_Float},
161 {(void *) & rfreq, (char *) "rot_frequency", (char *) "RotationFrequency", (char *) DEF_ROTFREQ, t_Float},
162 {(void *) & animate, (char *) "ttanimate", (char *) "TTAnimate", (char *) DEF_ANIMATE, t_String},
163 };
164
165 static OptionStruct desc[] =
166 {
167 {(char *) "-ttfont filename", (char *) "Text3d TrueType font file name"},
168 {(char *) "-/+no_split", (char *) "Text3d words splitting off/on"},
169 {(char *) "-extrusion float", (char *) "Text3d extrusion length"},
170 {(char *) "-rot_amplitude float", (char *) "Text3d rotation amplitude"},
171 {(char *) "-rot_frequency float", (char *) "Text3d rotation frequency"},
172 {(char *) "-ttanimate anim_name", (char *) "Text3d animation function"},
173 };
174
175 ENTRYPOINT ModeSpecOpt text3d_opts =
176 {sizeof opts / sizeof opts[0], opts, sizeof vars / sizeof vars[0], vars, desc};
177
178 #ifdef USE_MODULES
179 ModStruct text3d_description =
180 {"text3d", "init_text3d", "draw_text3d", "release_text3d",
181 "refresh_text3d", "change_text3d", (char *) NULL, &text3d_opts,
182 100000, 10, 1, 1, 64, 1.0, "",
183 "Shows 3D text", 0, NULL};
184 #endif
185
186 static text3dstruct *text3d = (text3dstruct *) NULL;
187
188 const double angle_speed = 2.5 / 180.0 * M_PI;
189
190 extern "C" {
191 typedef void (*t3dAnimProc) (text3dstruct * tp);
192 }
193
194 #ifdef __cplusplus
195 extern "C" {
196 #endif
197
198 static void t3d_anim_fullrandom(text3dstruct * tp);
199 static void t3d_anim_default(text3dstruct * tp);
200 static void t3d_anim_default2(text3dstruct * tp);
201 static void t3d_anim_none(text3dstruct * tp);
202 static void t3d_anim_crazy(text3dstruct * tp);
203 static void t3d_anim_updown(text3dstruct * tp);
204 static void t3d_anim_extrusion(text3dstruct * tp);
205 static void t3d_anim_rotatexy(text3dstruct * tp);
206 static void t3d_anim_rotateyz(text3dstruct * tp);
207 static void t3d_anim_frequency(text3dstruct * tp);
208 static void t3d_anim_amplitude(text3dstruct * tp);
209 static void t3d_anim_wander(text3dstruct * tp);
210 static char *fontfile = (char *) NULL;
211
212 #ifdef __cplusplus
213 }
214 #endif
215
216 static t3dAnimProc anim_array[] =
217 {
218 t3d_anim_fullrandom,
219 t3d_anim_default,
220 t3d_anim_default2,
221 t3d_anim_none,
222 t3d_anim_crazy,
223 t3d_anim_updown,
224 t3d_anim_extrusion,
225 t3d_anim_rotatexy,
226 t3d_anim_rotateyz,
227 t3d_anim_frequency,
228 t3d_anim_amplitude,
229 t3d_anim_wander,
230 };
231
232 static char * anim_names[] =
233 {
234 (char *) "Random",
235 (char *) "FullRandom",
236 (char *) "Default",
237 (char *) "Default2",
238 (char *) "None",
239 (char *) "Crazy",
240 (char *) "UpDown",
241 (char *) "Extrude",
242 (char *) "RotateXY",
243 (char *) "RotateYZ",
244 (char *) "Frequency", /* needs -rot_frequency /= 0.0 */
245 (char *) "Amplitude", /* and -rot_amplitude /= 0.0 */
246 (char *) "Wander",
247 (char *) NULL
248 };
249
250 static int anims=sizeof anim_array / sizeof anim_array[0] ;
251
252 /*
253 *-----------------------------------------------------------------------------
254 *-----------------------------------------------------------------------------
255 * Mode funcs.
256 *-----------------------------------------------------------------------------
257 *-----------------------------------------------------------------------------
258 */
259
260 /*
261 *-----------------------------------------------------------------------------
262 * Utils.
263 *-----------------------------------------------------------------------------
264 */
265
266 /* Select light stuff with the following defines */
267 #define TWO_LIGHTS
268 #define ALL_STUFF
269 //#define DIFFUSE_COLOR
270
271 #ifdef DIFFUSE_COLOR
272 static void
hsv_to_rgb(double h,double s,double v,double * r,double * g,double * b)273 hsv_to_rgb(double h, double s, double v,
274 double *r, double *g, double *b)
275 {
276 double xh = fmod(h * 360., 360) / 60.0,
277 i = floor(xh),
278 f = xh - i,
279 p1 = v * (1 - s),
280 p2 = v * (1 - (s * f)),
281 p3 = v * (1 - (s * (1 - f)));
282
283 switch ((int) i)
284 {
285 case 0:
286 *r = v;
287 *g = p3;
288 *b = p1;
289 break;
290 case 1:
291 *r = p2;
292 *g = v;
293 *b = p1;
294 break;
295 case 2:
296 *r = p1;
297 *g = v;
298 *b = p3;
299 break;
300 case 3:
301 *r = p1;
302 *g = p2;
303 *b = v;
304 break;
305 case 4:
306 *r = p3;
307 *g = p1;
308 *b = v;
309 break;
310 case 5:
311 *r = v;
312 *g = p1;
313 *b = p2;
314 break;
315 }
316 }
317 #endif /* DIFFUSE_COLOR */
318
319 /*-------------------------------------------------------------*/
spheric_camera(text3dstruct * tp,float center_x,float center_y,float center_z,float phi,float theta,float radius)320 static void spheric_camera(text3dstruct * tp,
321 float center_x, float center_y, float center_z,
322 float phi, float theta, float radius)
323 {
324 float x = center_x + cos(phi) * cos(theta) * radius;
325 float y = center_y + sin(phi) * cos(theta) * radius;
326 float z = center_z + sin(theta) * radius;
327
328 float vx = -cos(phi) * sin(theta) * radius;
329 float vy = -sin(phi) * sin(theta) * radius;
330 float vz = cos(theta) * radius;
331
332 glViewport(0, 0, tp->WinW, tp->WinH);
333 glMatrixMode(GL_PROJECTION);
334 glLoadIdentity();
335 gluPerspective(60, GLfloat(tp->WinW) / GLfloat(tp->WinH), 10, 10000);
336
337 glMatrixMode(GL_MODELVIEW);
338 glLoadIdentity();
339 gluLookAt(x, y, z, center_x, center_y, center_z, vx, vy, vz);
340 }
341
342 /*-------------------------------------------------------------*/
343 class GLTTGlyphTriangles:public GLTTGlyphTriangulator
344 {
345 public:
346 struct Triangle
347 {
348 FTGlyphVectorizer::POINT * p1;
349 FTGlyphVectorizer::POINT * p2;
350 FTGlyphVectorizer::POINT * p3;
351 };
352
353 Triangle *triangles;
354 int nTriangles;
355
356 GLTTboolean count_them;
357
GLTTGlyphTriangles(FTGlyphVectorizer * vectorizer)358 GLTTGlyphTriangles(FTGlyphVectorizer * vectorizer):
359 GLTTGlyphTriangulator(vectorizer)
360 {
361 triangles = 0;
362 nTriangles = 0;
363 count_them = GLTT_TRUE;
364 }
~GLTTGlyphTriangles()365 virtual ~GLTTGlyphTriangles()
366 {
367 delete[]triangles;
368 triangles = 0;
369 }
alloc()370 void alloc()
371 {
372 delete triangles;
373 triangles = new Triangle[nTriangles + 1];
374 }
triangle(FTGlyphVectorizer::POINT * p1,FTGlyphVectorizer::POINT * p2,FTGlyphVectorizer::POINT * p3)375 virtual void triangle(FTGlyphVectorizer::POINT * p1,
376 FTGlyphVectorizer::POINT * p2,
377 FTGlyphVectorizer::POINT * p3)
378 {
379 if (count_them)
380 {
381 ++nTriangles;
382 return;
383 }
384 triangles[nTriangles].p1 = p1;
385
386 triangles[nTriangles].p2 = p2;
387 triangles[nTriangles].p3 = p3;
388 ++nTriangles;
389 }
390 };
391
392 /*
393 *-----------------------------------------------------------------------------
394 * Animation functions.
395 *-----------------------------------------------------------------------------
396 */
397
398 /* defines for min/max/evolution factor of animations */
399 #define FAC_CAMERA 1.15
400 #define MAX_CAMERA 5.00
401
402 #define MIN_EXTRUSION 25.0
403 #define MAX_EXTRUSION 305.0
404 #define FAC_EXTRUSION 5.0
405
406 #define FAC_FREQ 0.15
407 #define FAC_AMPL 1.5
408
409 #define FAC_RAND 15
410
411 #ifdef __cplusplus
412 extern "C" {
413 #endif
414
415 /*-------------------------------------------------------------*/
416 static void
t3d_anim_default(text3dstruct * tp)417 t3d_anim_default(text3dstruct * tp)
418 {
419 tp->phi += tp->direction * angle_speed;
420 tp->theta += tp->direction * angle_speed;
421 }
422
423 /*-------------------------------------------------------------*/
424 static void
t3d_anim_default2(text3dstruct * tp)425 t3d_anim_default2(text3dstruct * tp)
426 {
427 tp->phi += tp->direction * angle_speed;
428 tp->theta += tp->direction * angle_speed * 2.0 ;
429 }
430
431 /*-------------------------------------------------------------*/
432 static void
t3d_anim_none(text3dstruct * tp)433 t3d_anim_none(text3dstruct * tp)
434 {
435 }
436
437 /*-------------------------------------------------------------*/
438 static void
t3d_anim_crazy(text3dstruct * tp)439 t3d_anim_crazy(text3dstruct * tp)
440 {
441 int key = NRAND(32);
442
443 switch (key)
444 {
445 case 0:
446 case 1:
447 case 2:
448 case 3:
449 tp->theta += angle_speed;
450 break;
451 case 4:
452 case 5:
453 case 6:
454 case 7:
455 tp->theta -= angle_speed;
456 break;
457 case 8:
458 case 9:
459 case 10:
460 case 11:
461 tp->phi -= angle_speed;
462 break;
463 case 12:
464 case 13:
465 case 14:
466 case 15:
467 tp->phi += angle_speed;
468 break;
469 case 16:
470 case 17:
471 if (tp->camera_dist / FAC_CAMERA > tp->ref_camera_dist)
472 tp->camera_dist /= FAC_CAMERA;
473 break;
474 case 18:
475 case 19:
476 if (tp->camera_dist * FAC_CAMERA < (tp->ref_camera_dist * MAX_CAMERA))
477 tp->camera_dist *= FAC_CAMERA;
478 break;
479 case 20:
480 if ((tp->extrusion - FAC_EXTRUSION) > MIN_EXTRUSION)
481 tp->extrusion -= FAC_EXTRUSION;
482 break;
483 case 21:
484 if ((tp->extrusion + FAC_EXTRUSION) < MAX_EXTRUSION)
485 tp->extrusion += FAC_EXTRUSION;
486 break;
487 case 22:
488 case 23:
489 tp->rampl /= FAC_AMPL;
490 break;
491 case 24:
492 case 25:
493 tp->rampl *= FAC_AMPL;
494 break;
495 case 26:
496 case 27:
497 tp->rfreq *= FAC_FREQ;
498 break;
499 case 28:
500 case 29:
501 tp->rfreq /= FAC_FREQ;
502 break;
503 }
504 }
505
506 static void
t3d_anim_updown(text3dstruct * tp)507 t3d_anim_updown(text3dstruct * tp)
508 {
509 if (tp->direction > 0)
510 {
511 if (tp->camera_dist / FAC_CAMERA > tp->ref_camera_dist)
512 tp->camera_dist /= FAC_CAMERA;
513 else
514 tp->direction *=-1;
515 }
516 else
517 {
518 if (tp->camera_dist * FAC_CAMERA < (tp->ref_camera_dist * MAX_CAMERA))
519 tp->camera_dist *= FAC_CAMERA;
520 else
521 tp->direction *=-1;
522 }
523 }
524
525 static void
t3d_anim_extrusion(text3dstruct * tp)526 t3d_anim_extrusion(text3dstruct * tp)
527 {
528 if (tp->direction > 0)
529 {
530 if ((tp->extrusion - FAC_EXTRUSION) > MIN_EXTRUSION)
531 tp->extrusion -= FAC_EXTRUSION;
532 else
533 tp->direction *=-1;
534 }
535 else
536 {
537 if ((tp->extrusion + FAC_EXTRUSION) < MAX_EXTRUSION)
538 tp->extrusion += FAC_EXTRUSION;
539 else
540 tp->direction *=-1;
541 }
542 }
543
544 static void
t3d_anim_rotatexy(text3dstruct * tp)545 t3d_anim_rotatexy(text3dstruct * tp)
546 {
547 tp->phi += tp->direction * angle_speed;
548 }
549
550 static void
t3d_anim_rotateyz(text3dstruct * tp)551 t3d_anim_rotateyz(text3dstruct * tp)
552 {
553 tp->theta += tp->direction * angle_speed;
554 }
555
556 static void
t3d_anim_frequency(text3dstruct * tp)557 t3d_anim_frequency(text3dstruct * tp)
558 {
559 /* Better visual if freq is a small value < 0.05 */
560 if (tp->direction > 0)
561 {
562 tp->rfreq /= FAC_FREQ;
563 }
564 else
565 {
566 tp->rfreq *= FAC_FREQ;
567 }
568
569 if (NRAND(100) < FAC_RAND )
570 tp->direction *=-1;
571 }
572
573 static void
t3d_anim_amplitude(text3dstruct * tp)574 t3d_anim_amplitude(text3dstruct * tp)
575 {
576 if (tp->direction > 0)
577 {
578 tp->rampl /= FAC_AMPL;
579 }
580 else
581 {
582 tp->rampl *= FAC_AMPL;
583 }
584
585 if (NRAND(100) < FAC_RAND )
586 tp->direction *=-1;
587 }
588
589 static void
t3d_anim_fullrandom(text3dstruct * tp)590 t3d_anim_fullrandom(text3dstruct * tp)
591 {
592 static int animation=NRAND(anims);
593 if (NRAND(100) < FAC_RAND/5 || animation <= 1)
594 {
595 /* change animation */
596 animation = NRAND(anims);
597 }
598 anim_array[animation](tp);
599 }
600
601 static void
t3d_anim_wander(text3dstruct * tp)602 t3d_anim_wander(text3dstruct * tp)
603 {
604 static int frame = 0;
605 GLfloat x, y, z;
606 #define SINOID(SCALE,SIZE) \
607 ((((1 + sin((frame * (SCALE)) / 2 * M_PI)) / 2.0) * (SIZE)) - (SIZE)/2)
608
609 x = SINOID(0.061, angle_speed);
610 y = SINOID(0.083, angle_speed * 2.0);
611 z = SINOID(0.075, MAX_CAMERA * 10.0);
612 frame++;
613 tp->phi += tp->direction * x;
614 tp->theta += tp->direction * y;
615 tp->camera_dist += tp->direction * z;
616 }
617
618 #ifdef __cplusplus
619 }
620 #endif
621
622
623 /*-------------------------------------------------------------*/
624 /*-------------------------------------------------------------*/
625 /*
626 *-----------------------------------------------------------------------------
627 * "Main" local funcs.
628 *-----------------------------------------------------------------------------
629 */
630
631 void
reshape_text3d(ModeInfo * mi,int width,int height)632 reshape_text3d(ModeInfo * mi, int width, int height)
633 {
634 text3dstruct *tp = &text3d[MI_SCREEN(mi)];
635
636 glViewport(0, 0, tp->WinW = (GLint) width, tp->WinH = (GLint) height);
637
638 glMatrixMode(GL_PROJECTION);
639 glLoadIdentity();
640 gluPerspective(60.0, (GLdouble) width / (GLdouble) height, 10, 10000);
641 glMatrixMode(GL_MODELVIEW);
642 }
643
644 /*-------------------------------------------------------------*/
645 static void
Animate(text3dstruct * tp)646 Animate(text3dstruct * tp)
647 {
648 anim_array[tp->animation](tp);
649 }
650
651 /*-------------------------------------------------------------*/
652 static void
Draw(text3dstruct * tp,Display * display,Window window)653 Draw(text3dstruct * tp,
654 Display * display,
655 Window window)
656 {
657 int text_length;
658 char *c_text;
659
660 #ifndef STANDALONE
661 if (!nosplit)
662 {
663 text_length = index_dir(tp->words, (char *) " ");
664 if (text_length == 0)
665 text_length = strlen(tp->words);
666 if ((c_text = (char *) malloc(text_length)) != NULL)
667 strncpy(c_text, tp->words, text_length);
668 }
669 else
670 #endif
671 {
672 c_text = tp->words_start;
673 text_length = strlen(tp->words_start);
674 }
675 GLTTFont font(tp->face);
676
677 if (!font.create(DEF_FONTSIZE))
678 return;
679
680 FTGlyphVectorizer *vec = new FTGlyphVectorizer[text_length];
681 GLTTGlyphTriangles **tri = new GLTTGlyphTriangles *[text_length];
682
683 int i;
684
685 for (i = 0; i < text_length; ++i)
686 tri[i] = new GLTTGlyphTriangles(vec + i);
687
688 if (tp->camera_dist == 0.0)
689 /* PURIFY reports an Array Bounds Read on the next line */
690 tp->ref_camera_dist = tp->camera_dist = font.getWidth(c_text) * 0.75;
691 double min_y = 1e20;
692 double max_y = -1e20;
693 double size_x = 0.0;
694
695 for (i = 0; i < text_length; ++i)
696 {
697 int ch = (unsigned char) c_text[i];
698
699 #if ((XMESA_MAJOR_VERSION > 3 ) || (( XMESA_MAJOR_VERSION == 3 ) && (XMESA_MINOR_VERSION > 0 )))
700 glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
701 glPixelStorei(GL_UNPACK_SWAP_BYTES, GL_FALSE);
702 glPixelStorei(GL_UNPACK_LSB_FIRST, GL_FALSE);
703 glPixelStorei(GL_UNPACK_SKIP_ROWS, 0);
704 glPixelStorei(GL_UNPACK_SKIP_PIXELS, 0);
705 glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
706 #endif
707
708 FTGlyph *g = font.getFont()->getGlyph(ch);
709
710 if (g == 0)
711 continue;
712 FTGlyphVectorizer & v = vec[i];
713 v.setPrecision(10.0);
714 /* PURIFY reports an Array Bounds Write on the next line */
715 if (!v.init(g))
716 continue;
717
718 size_x += v.getAdvance();
719
720 if (!v.vectorize())
721 continue;
722
723 for (int c = 0; c < v.getNContours(); ++c)
724 {
725 FTGlyphVectorizer::Contour * contour = v.getContour(c);
726 if (contour == 0)
727 continue;
728 for (int j = 0; j < contour->nPoints; ++j)
729 {
730 FTGlyphVectorizer::POINT * point = contour->points + j;
731 if (point->y < min_y)
732 min_y = point->y;
733 if (point->y > max_y)
734 max_y = point->y;
735 point->data = (void *) new double[6];
736 }
737 }
738 GLTTGlyphTriangles *t = tri[i];
739
740 if (!t->init(g))
741 continue;
742
743 t->count_them = GLTT_TRUE;
744 t->nTriangles = 0;
745 t->triangulate();
746
747 t->count_them = GLTT_FALSE;
748 t->alloc();
749 t->nTriangles = 0;
750 t->triangulate();
751 }
752
753 #ifndef STANDALONE
754 if (!nosplit)
755 free(c_text);
756 #endif
757 if (size_x == 0.0)
758 {
759 (void) fprintf(stderr, "Please give something to draw !\n");
760 delete[]vec;
761 return;
762 }
763
764 double y_delta = (min_y + max_y) / 2. + min_y + 50;
765
766 for (i = 0; i < text_length; ++i)
767 {
768
769 #if ((XMESA_MAJOR_VERSION > 3 ) || (( XMESA_MAJOR_VERSION == 3 ) && (XMESA_MINOR_VERSION > 0 )))
770 glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
771 glPixelStorei(GL_UNPACK_SWAP_BYTES, GL_FALSE);
772 glPixelStorei(GL_UNPACK_LSB_FIRST, GL_FALSE);
773 glPixelStorei(GL_UNPACK_SKIP_ROWS, 0);
774 glPixelStorei(GL_UNPACK_SKIP_PIXELS, 0);
775 glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
776 #endif
777
778 FTGlyphVectorizer & v = vec[i];
779
780 for (int c = 0; c < v.getNContours(); ++c)
781 {
782 FTGlyphVectorizer::Contour * contour = v.getContour(c);
783 if (contour == 0)
784 continue;
785 for (int j = 0; j < contour->nPoints; ++j)
786 {
787 FTGlyphVectorizer::POINT * point = contour->points + j;
788 point->y -= y_delta;
789 }
790 }
791 }
792
793
794 #ifdef ALL_STUFF
795 float front_emission[4] = {0.1, 0.1, 0.1, 0};
796 float front_ambient[4] = {0.2, 0.2, 0.2, 0};
797 float front_diffuse[4] = {0.95, 0.95, 0.8, 0};
798 float back_diffuse[4] = {0.75, 0.75, 0.95, 0};
799 float front_specular[4] = {0.6, 0.6, 0.6, 0};
800
801 glMaterialfv(GL_FRONT, GL_EMISSION, front_emission);
802 glMaterialfv(GL_FRONT, GL_AMBIENT, front_ambient);
803 glMaterialfv(GL_FRONT, GL_DIFFUSE, front_diffuse);
804 glMaterialfv(GL_FRONT, GL_SPECULAR, front_specular);
805 glMaterialf(GL_FRONT, GL_SHININESS, 32.0);
806 #ifdef TWO_LIGHTS
807 float light1_ambient[4] = {0.3, 0.3, 0.3, 1};
808 float light1_diffuse[4] = {0.9, 0.9, 0.9, 1}; /* A "white" light */
809 float light1_specular[4] = {0.7, 0.7, 0.7, 1};
810 float light1_position[4] = {-1, 1, 1, 0};
811
812 glLightfv(GL_LIGHT1, GL_AMBIENT, light1_ambient);
813 glLightfv(GL_LIGHT1, GL_DIFFUSE, light1_diffuse);
814 glLightfv(GL_LIGHT1, GL_SPECULAR, light1_specular);
815 glLightfv(GL_LIGHT1, GL_POSITION, light1_position);
816 glEnable(GL_LIGHT1);
817
818 float light2_ambient[4] = {0.1, 0.1, 0.1, 1};
819 float light2_diffuse[4] = {0.85, 0.3, 0.3, 1}; /* A "red" light */
820 float light2_specular[4] = {0.6, 0.6, 0.6, 1};
821 float light2_position[4] = {1, -1, -1, 0};
822
823 glLightfv(GL_LIGHT2, GL_AMBIENT, light2_ambient);
824 glLightfv(GL_LIGHT2, GL_DIFFUSE, light2_diffuse);
825 glLightfv(GL_LIGHT2, GL_SPECULAR, light2_specular);
826 glLightfv(GL_LIGHT2, GL_POSITION, light2_position);
827 glEnable(GL_LIGHT2);
828 #else
829 GLfloat pos[4] = {-1.0, 1.0, 1.0, 0.0};
830
831 glLightfv(GL_LIGHT0, GL_POSITION, pos);
832 glEnable(GL_LIGHT0);
833 #endif /* TWO_LIGHTS */
834
835 float back_color[4] = {0.2, 0.2, 0.6, 0};
836
837 glMaterialfv(GL_BACK, GL_DIFFUSE, back_color);
838 glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, GL_FALSE);
839 glCullFace(GL_BACK);
840 glFrontFace(GL_CCW);
841 glEnable(GL_CULL_FACE);
842
843 glColorMaterial(GL_FRONT, GL_DIFFUSE);
844 glEnable(GL_COLOR_MATERIAL);
845 #endif /* ALL_STUFF */
846
847 spheric_camera(tp, tp->center_x,
848 tp->center_y + size_x / 2.,
849 0,
850 tp->phi, tp->theta + M_PI / 2, tp->camera_dist);
851 glClearColor(0, 0, 0, 0);
852 glEnable(GL_DEPTH_TEST);
853 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
854
855 glMatrixMode(GL_MODELVIEW);
856 glPushMatrix();
857
858 #ifdef ALL_STUFF
859 glEnable(GL_LIGHTING);
860 glShadeModel(GL_SMOOTH);
861 glEnable(GL_NORMALIZE);
862 #endif
863
864 double base_x = 0.0;
865
866 for (i = 0; i < text_length; ++i)
867 {
868
869 #if ((XMESA_MAJOR_VERSION > 3 ) || (( XMESA_MAJOR_VERSION == 3 ) && (XMESA_MINOR_VERSION > 0 )))
870 glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
871 glPixelStorei(GL_UNPACK_SWAP_BYTES, GL_FALSE);
872 glPixelStorei(GL_UNPACK_LSB_FIRST, GL_FALSE);
873 glPixelStorei(GL_UNPACK_SKIP_ROWS, 0);
874 glPixelStorei(GL_UNPACK_SKIP_PIXELS, 0);
875 glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
876 #endif
877
878 FTGlyphVectorizer & v = vec[i];
879
880 int c;
881
882 for (c = 0; c < v.getNContours(); ++c)
883 {
884 FTGlyphVectorizer::Contour * contour = v.getContour(c);
885 if (contour == 0)
886 continue;
887
888 for (int j = 0; j < contour->nPoints; ++j)
889 {
890 FTGlyphVectorizer::POINT * point = contour->points + j;
891 double cx = -point->y;
892 double cy = base_x + point->x;
893 double phi = sin(cy * tp->rfreq) * tp->rampl * M_PI / 2.;
894 double rcx = cx * cos(phi);
895 double rcz = cx * sin(phi);
896
897 double *p = (double *) point->data;
898 double *n = p + 3;
899
900 p[0] = rcx;
901 p[1] = cy;
902 p[2] = rcz;
903
904 n[0] = -sin(phi);
905 n[1] = 0.;
906 n[2] = cos(phi);
907 }
908 }
909
910 GLTTGlyphTriangles::Triangle * triangles = tri[i]->triangles;
911 int nTriangles = tri[i]->nTriangles;
912
913 glBegin(GL_TRIANGLES);
914
915 for (int j = 0; j < nTriangles; ++j)
916 {
917 GLTTGlyphTriangles::Triangle & t = triangles[j];
918
919 double *p1 = ((double *) t.p1->data);
920 double *p2 = ((double *) t.p2->data);
921 double *p3 = ((double *) t.p3->data);
922 double *n1 = p1 + 3;
923 double *n2 = p2 + 3;
924 double *n3 = p3 + 3;
925
926 #ifdef ALL_STUFF
927 glColor4fv(front_diffuse);
928 #endif
929
930 glNormal3dv(n1);
931 glVertex3dv(p1);
932 glNormal3dv(n2);
933 glVertex3dv(p2);
934 glNormal3dv(n3);
935 glVertex3dv(p3);
936
937 #ifdef ALL_STUFF
938 glColor4fv(back_diffuse);
939 #endif
940
941 glNormal3d(-n3[0], 0., -n3[2]);
942 glVertex3d(p3[0] - n3[0] * tp->extrusion,
943 p3[1],
944 p3[2] - n3[2] * tp->extrusion);
945 glNormal3d(-n2[0], 0., -n2[2]);
946 glVertex3d(p2[0] - n2[0] * tp->extrusion,
947 p2[1],
948 p2[2] - n2[2] * tp->extrusion);
949 glNormal3d(-n1[0], 0., -n1[2]);
950 glVertex3d(p1[0] - n1[0] * tp->extrusion,
951 p1[1],
952 p1[2] - n1[2] * tp->extrusion);
953 }
954 glEnd();
955
956 for (c = 0; c < v.getNContours(); ++c)
957 {
958 FTGlyphVectorizer::Contour * contour = v.getContour(c);
959 if (contour == 0)
960 continue;
961 glBegin(GL_QUAD_STRIP);
962 for (int j = 0; j <= contour->nPoints; ++j)
963 {
964 int j1 = (j < contour->nPoints) ? j : 0;
965 int j0 = (j1 == 0) ? (contour->nPoints - 1) : (j1 - 1);
966
967 FTGlyphVectorizer::POINT * point0 = contour->points + j0;
968 FTGlyphVectorizer::POINT * point1 = contour->points + j1;
969 double *p0 = (double *) point0->data;
970 double *p1 = (double *) point1->data;
971 double *e = p0 + 3;
972 double vx = p1[0] - p0[0];
973 double vy = p1[1] - p0[1];
974 double vz = p1[2] - p0[2];
975 double nx = -vy * e[2];
976 double ny = e[2] * vx - vz * e[0];
977 double nz = e[0] * vy;
978 #ifdef DIFFUSE_COLOR
979 double u = double ((j * 2) % contour->nPoints) / double (contour->nPoints);
980 double r, g, b;
981
982 hsv_to_rgb(u, 0.7, 0.7, &r, &g, &b);
983 glColor4f(r, g, b, 1); // diffuse color of material
984 #else
985 GLfloat blue[4] = {0.35, 0.35, 1.0, 1.0};
986 glColor4fv(blue);
987 #endif
988
989 glNormal3f(nx, ny, nz);
990 glVertex3f(p0[0] - e[0] * tp->extrusion,
991 p0[1],
992 p0[2] - e[2] * tp->extrusion);
993 glNormal3f(nx, ny, nz);
994 glVertex3f(p0[0], p0[1], p0[2]);
995 }
996 glEnd();
997 }
998
999 base_x += v.getAdvance();
1000 }
1001
1002 #ifdef ALL_STUFF
1003 glDisable(GL_NORMALIZE);
1004 glDisable(GL_LIGHTING);
1005 glShadeModel(GL_FLAT);
1006 #endif
1007 glPopMatrix();
1008
1009 glXSwapBuffers(display, window);
1010
1011 for (i = 0; i < text_length; ++i)
1012 {
1013
1014 #if ((XMESA_MAJOR_VERSION > 3 ) || (( XMESA_MAJOR_VERSION == 3 ) && (XMESA_MINOR_VERSION > 0 )))
1015 glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
1016 glPixelStorei(GL_UNPACK_SWAP_BYTES, GL_FALSE);
1017 glPixelStorei(GL_UNPACK_LSB_FIRST, GL_FALSE);
1018 glPixelStorei(GL_UNPACK_SKIP_ROWS, 0);
1019 glPixelStorei(GL_UNPACK_SKIP_PIXELS, 0);
1020 glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
1021 #endif
1022
1023 delete tri[i];
1024
1025 FTGlyphVectorizer & v = vec[i];
1026 for (int c = 0; c < v.getNContours(); ++c)
1027 {
1028 FTGlyphVectorizer::Contour * contour = v.getContour(c);
1029 if (contour == 0)
1030 continue;
1031 for (int j = 0; j < contour->nPoints; ++j)
1032 {
1033 FTGlyphVectorizer::POINT * point = contour->points + j;
1034 delete[](double *) point->data;
1035 point->data = 0;
1036 }
1037 }
1038 }
1039
1040 delete[]tri;
1041 delete[]vec;
1042 }
1043
1044 /*
1045 *-----------------------------------------------------------------------------
1046 *-----------------------------------------------------------------------------
1047 * Xlock hooks.
1048 *-----------------------------------------------------------------------------
1049 *-----------------------------------------------------------------------------
1050 */
1051
1052 /*
1053 *-----------------------------------------------------------------------------
1054 * The display is being taken away from us. Free up malloc'ed
1055 * memory and X resources that we've alloc'ed. Only called
1056 * once, we must zap everything for every screen.
1057 *-----------------------------------------------------------------------------
1058 */
1059
1060 ENTRYPOINT void
release_text3d(ModeInfo * mi)1061 release_text3d(ModeInfo * mi)
1062 {
1063 if (text3d != NULL)
1064 {
1065 for (int screen = 0; screen < MI_NUM_SCREENS(mi); screen++)
1066 {
1067 text3dstruct *tp = &text3d[screen];
1068
1069 if (tp->face)
1070 delete tp->face;
1071 }
1072 free(text3d);
1073 text3d = (text3dstruct *) NULL;
1074 }
1075 FreeAllGL(mi);
1076 }
1077
1078 /*
1079 *-----------------------------------------------------------------------------
1080 * Initialize text3d. Called each time the window changes.
1081 *-----------------------------------------------------------------------------
1082 */
1083
1084 ENTRYPOINT void
init_text3d(ModeInfo * mi)1085 init_text3d(ModeInfo * mi)
1086 {
1087 int i;
1088 text3dstruct *tp;
1089
1090
1091 if (text3d == NULL)
1092 {
1093 /*MI_INIT(mi, text3d);*/
1094 if ((text3d = (text3dstruct *) calloc(MI_NUM_SCREENS(mi),
1095 sizeof(text3dstruct))) == NULL)
1096 return;
1097 }
1098 tp = &text3d[MI_SCREEN(mi)];
1099 tp->wire = MI_IS_WIREFRAME(mi);
1100 tp->extrusion = extrusion;
1101 tp->rampl = rampl;
1102 tp->rfreq = rfreq;
1103 tp->camera_dist = 0.0;
1104
1105 /* Get animation function */
1106 tp->animation = 0; /* Not found equals "Random" */
1107 tp->direction = (LRAND() & 1) ? 1 : -1; /* random direction */
1108 tp->rampl *= tp->direction;
1109 tp->rfreq *= tp->direction;
1110 for(i=0;anim_names[i] != NULL;i++)
1111 {
1112 if ( !strcmp( anim_names[i], animate ) )
1113 {
1114 tp->animation = i;
1115 break;
1116 }
1117 }
1118 if (!tp->animation)
1119 {
1120 /* Random !!! */
1121 tp->animation = NRAND(anims);
1122 }
1123 else
1124 {
1125 tp->animation --;
1126 }
1127
1128 if (MI_IS_DEBUG(mi))
1129 {
1130 (void) fprintf(stderr,
1131 "%s:\n\ttp->animation[%d]=%s\n",
1132 MI_NAME(mi), tp->animation, anim_names[tp->animation+1]);
1133 }
1134
1135 tp->counter = 0;
1136 #ifdef STANDALONE
1137 if ((fontfile = (char *) malloc(strlen(mode_font) + 10)) != NULL)
1138 sprintf(fontfile, "%s%s", mode_font, "arial.ttf");
1139 #else
1140 fontfile = getModeFont(mode_font);
1141 #endif
1142 if (!fontfile) {
1143 MI_CLEARWINDOW(mi);
1144 release_text3d(mi);
1145 return;
1146 }
1147 tp->face = new FTFace;
1148 if (!tp->face || !tp->face->open(fontfile)) {
1149 (void) fprintf(stderr, "%s: unable to open True Type font %s!\n", MI_NAME(mi), fontfile);
1150 MI_CLEARWINDOW(mi);
1151 release_text3d(mi);
1152 return;
1153 }
1154 if (MI_IS_DEBUG(mi)) {
1155 (void) fprintf(stderr,
1156 "%s:\n\tfontfile=%s .\n", MI_NAME(mi), fontfile);
1157 }
1158
1159 /* Do not free fontfile getModeFont handles potential leak */
1160 if ((tp->glx_context = init_GL(mi)) != NULL)
1161 {
1162
1163 reshape_text3d(mi, MI_WIDTH(mi), MI_HEIGHT(mi));
1164 /*glDrawBuffer(GL_BACK); */
1165 if (MI_IS_DEBUG(mi))
1166 {
1167 (void) fprintf(stderr,
1168 "%s:\n\tcamera_dist=%.1f\n\ttheta=%.1f\n\tphi=%.1f\n\textrusion=%.1f\n\trampl=%.1f.\n\trfreq=%.1f\n\tdirection=%d\n",
1169 MI_NAME(mi), tp->camera_dist, tp->theta, tp->phi,
1170 tp->extrusion, tp->rampl,tp->rfreq,tp->direction);
1171 }
1172 /*
1173 glXSwapBuffers(display, window);
1174 */
1175
1176 }
1177 else
1178 {
1179 MI_CLEARWINDOW(mi);
1180 }
1181
1182 /* Initialize displayed string */
1183 tp->words_start = tp->words =
1184 getWords(MI_SCREEN(mi), MI_NUM_SCREENS(mi));
1185 if (MI_IS_DEBUG(mi))
1186 {
1187 (void) fprintf(stderr,
1188 "%s words:\n%s\n",
1189 MI_NAME(mi), tp->words);
1190 }
1191
1192 }
1193
1194 /*
1195 *-----------------------------------------------------------------------------
1196 * Called by the mainline code periodically to update the display.
1197 *-----------------------------------------------------------------------------
1198 */
1199 ENTRYPOINT void
draw_text3d(ModeInfo * mi)1200 draw_text3d(ModeInfo * mi)
1201 {
1202 Display *display = MI_DISPLAY(mi);
1203 Window window = MI_WINDOW(mi);
1204 text3dstruct *tp;
1205
1206 if (text3d == NULL) {
1207 return;
1208 }
1209 tp = &text3d[MI_SCREEN(mi)];
1210
1211 MI_IS_DRAWN(mi) = True;
1212 if (!tp->glx_context)
1213 return;
1214 tp->counter = tp->counter + 1;
1215 #ifndef STANDALONE
1216 if (tp->counter > (MI_CYCLES(mi) & !nosplit))
1217 {
1218 int text_length = index_dir(tp->words, (char *) " ");
1219
1220 /* Every now and then, get a new word */
1221 if (text_length == 0)
1222 text_length = strlen(tp->words);
1223 tp->counter = 0;
1224 tp->words += text_length;
1225 text_length = strlen(tp->words);
1226 if (text_length == 0)
1227 {
1228 tp->words_start = tp->words =
1229 getWords(MI_SCREEN(mi), MI_NUM_SCREENS(mi));
1230 }
1231 }
1232 #endif
1233 glDrawBuffer(GL_BACK);
1234 #ifdef WIN32
1235 wglMakeCurrent(hdc, tp->glx_context);
1236 #else
1237 glXMakeCurrent(display, window, *(tp->glx_context));
1238 #endif
1239 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
1240
1241 Draw(tp, display, window);
1242 Animate(tp);
1243 if (MI_IS_DEBUG(mi))
1244 {
1245 (void) fprintf(stderr,
1246 "%s:\n\tcamera_dist=%.1f\n\ttheta=%.1f\n\tphi=%.1f\n\textrusion=%.1f\n\trampl=%.1f\n\trfreq=%.1f\n\tdirection=%d\n",
1247 MI_NAME(mi), tp->camera_dist, tp->theta, tp->phi,
1248 tp->extrusion, tp->rampl,tp->rfreq,tp->direction);
1249 }
1250 }
1251
1252 #ifndef STANDALONE
1253 ENTRYPOINT void
refresh_text3d(ModeInfo * mi)1254 refresh_text3d(ModeInfo * mi)
1255 {
1256 /* Do nothing, it will refresh by itself :) */
1257 }
1258
1259 ENTRYPOINT void
change_text3d(ModeInfo * mi)1260 change_text3d(ModeInfo * mi)
1261 {
1262 text3dstruct *tp;
1263
1264 if (text3d == NULL) {
1265 return;
1266 }
1267 tp = &text3d[MI_SCREEN(mi)];
1268
1269 if (!tp->glx_context)
1270 return;
1271 glDrawBuffer(GL_BACK);
1272 #ifdef WIN32
1273 wglMakeCurrent(hdc, tp->glx_context);
1274 #else
1275 glXMakeCurrent(MI_DISPLAY(mi), MI_WINDOW(mi), *(tp->glx_context));
1276 #endif
1277 }
1278 #endif
1279
1280 XSCREENSAVER_MODULE ("Text3d", text3d)
1281
1282 #endif /* MODE_text3d */
1283