<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
"http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv=Content-Type content="text/html; charset=utf8">
<title>/usr/web/sources/contrib/andrey/glenda.c - Plan 9 from Bell Labs</title>
<!-- THIS FILE IS AUTOMATICALLY GENERATED. -->
<!-- EDIT sources.tr INSTEAD. -->
</meta>
</head>
<body>
<p style="margin-top: 0; margin-bottom: 0.17in"></p>
<p style="line-height: 1.2em; margin-left: 1.00in; text-indent: 0.00in; margin-right: 1.00in; margin-top: 0; margin-bottom: 0; text-align: center;">
<span style="font-size: 10pt"><a href="/plan9/">Plan 9 from Bell Labs</a>&rsquo;s /usr/web/sources/contrib/andrey/glenda.c</span></p>
<p style="margin-top: 0; margin-bottom: 0.17in"></p>
<p style="margin-top: 0; margin-bottom: 0.17in"></p>
<center><font size=-1>
Copyright © 2009 Alcatel-Lucent.<br />
Distributed under the
<a href="/plan9/license.html">Lucent Public License version 1.02</a>.
<br />
<a href="/plan9/download.html">Download the Plan 9 distribution.</a>
</font>
</center>
<p style="margin-top: 0; margin-bottom: 0.17in"></p>
<table width="100%" cellspacing=0 border=0><tr><td align="center">
<table cellspacing=0 cellpadding=5 bgcolor="#eeeeff"><tr><td align="left">
<pre>
<!-- END HEADER -->
/*
* Ported to Plan 9 from XScreensaver by [email protected], 10/03
*
* modified with extra glendas: 11/03
*/

/* plan9-related stuff */
#include "plan9.h"
Image *glenda;
Image *mask;

ulong frames = 0;
vlong tbegin, tend;



#define POINT_COUNT 16
#define LINE_COUNT 32

#define ANGLE_SCALE 0.001

struct line_info
{
       char li_ip;
       char li_iq;
       char li_color;
       char li_pad;
};

struct point_state
{
       short old_x, old_y;
       short new_x, new_y;
};

struct hyper_state
{
       char hs_stop;
       char hs_icon;
       char hs_resize;
       char hs_redraw;
       float hs_two_observer_z;
       float hs_offset_x;
       float hs_offset_y;
       float hs_unit_scale;
       int hs_delay;
       double hs_cos_xy, hs_sin_xy;
       double hs_cos_xz, hs_sin_xz;
       double hs_cos_yz, hs_sin_yz;
       double hs_cos_xw, hs_sin_xw;
       double hs_cos_yw, hs_sin_yw;
       double hs_cos_zw, hs_sin_zw;
       double hs_ref_ax, hs_ref_ay, hs_ref_az, hs_ref_aw;
       double hs_ref_bx, hs_ref_by, hs_ref_bz, hs_ref_bw;
       double hs_ref_cx, hs_ref_cy, hs_ref_cz, hs_ref_cw;
       double hs_ref_dx, hs_ref_dy, hs_ref_dz, hs_ref_dw;
       struct point_state hs_points[POINT_COUNT];
};

static const struct line_info line_table[LINE_COUNT];

static void init (struct hyper_state *hs);
static void hyper (struct hyper_state *hs);
static void check_events (struct hyper_state *hs);
static void set_sizes (struct hyper_state *hs, int width, int height);

static struct hyper_state hyper_state;

void
screenhack (void)
{
       struct hyper_state *hs;

       hs = &amp;hyper_state;

       init (hs);

       hyper (hs);
}


static void
init (struct hyper_state *hs)
{
       int delay, width, height;
       float observer_z;


       observer_z = frand()*5.0;
       if (observer_z &lt; 1.125)
               observer_z = 1.125;
       hs-&gt;hs_two_observer_z = 2.0 * observer_z;

       width = Dx(screen-&gt;r);
       height = Dy(screen-&gt;r);
       set_sizes (hs, width, height);

       delay = 10;
       hs-&gt;hs_delay = delay;


       hs-&gt;hs_ref_ax = 1.0, hs-&gt;hs_ref_ay = 0.0, hs-&gt;hs_ref_az = 0.0, hs-&gt;hs_ref_aw = 0.0;
       hs-&gt;hs_ref_bx = 0.0, hs-&gt;hs_ref_by = 1.0, hs-&gt;hs_ref_bz = 0.0, hs-&gt;hs_ref_bw = 0.0;
       hs-&gt;hs_ref_cx = 0.0, hs-&gt;hs_ref_cy = 0.0, hs-&gt;hs_ref_cz = 1.0, hs-&gt;hs_ref_cw = 0.0;
       hs-&gt;hs_ref_dx = 0.0, hs-&gt;hs_ref_dy = 0.0, hs-&gt;hs_ref_dz = 0.0, hs-&gt;hs_ref_dw = 1.0;

       {
               double xy;
               double xz;
               double yz;
               double xw;
               double yw;
               double zw;
               double cos_xy, sin_xy;
               double cos_xz, sin_xz;
               double cos_yz, sin_yz;
               double cos_xw, sin_xw;
               double cos_yw, sin_yw;
               double cos_zw, sin_zw;

/*              xy = 3 * ANGLE_SCALE;
               xz = 5 * ANGLE_SCALE;
               yz = 0 * ANGLE_SCALE;
               xw = 0 * ANGLE_SCALE;
               yw = 10 * ANGLE_SCALE;
               zw = 0 * ANGLE_SCALE;
*/
               xy = (nrand(3)+2) * ANGLE_SCALE;
               xz = (nrand(7)+2) * ANGLE_SCALE;
               yz = nrand(3) * ANGLE_SCALE;
               xw = nrand(5) * ANGLE_SCALE;
               yw = (nrand(10)+5) * ANGLE_SCALE;
               zw = nrand(3) * ANGLE_SCALE;

               cos_xy = cos (xy), sin_xy = sin (xy);
               hs-&gt;hs_cos_xy = cos_xy, hs-&gt;hs_sin_xy = sin_xy;
               cos_xz = cos (xz), sin_xz = sin (xz);
               hs-&gt;hs_cos_xz = cos_xz, hs-&gt;hs_sin_xz = sin_xz;
               cos_yz = cos (yz), sin_yz = sin (yz);
               hs-&gt;hs_cos_yz = cos_yz, hs-&gt;hs_sin_yz = sin_yz;
               cos_xw = cos (xw), sin_xw = sin (xw);
               hs-&gt;hs_cos_xw = cos_xw, hs-&gt;hs_sin_xw = sin_xw;
               cos_yw = cos (yw), sin_yw = sin (yw);
               hs-&gt;hs_cos_yw = cos_yw, hs-&gt;hs_sin_yw = sin_yw;
               cos_zw = cos (zw), sin_zw = sin (zw);
               hs-&gt;hs_cos_zw = cos_zw, hs-&gt;hs_sin_zw = sin_zw;
       }
}


static void
hyper (struct hyper_state *hs)
{
       int roted;

       roted = 0;

       tbegin = nsec();

       for (;;)
       {
               int icon;
               int resize;
               char moved[POINT_COUNT];
               int redraw = 0;
               int stop;
               int delay;

               check_events (hs);

               icon = hs-&gt;hs_icon;
               resize = hs-&gt;hs_resize;
               if (icon || !(roted | resize))
                       goto skip1;

               {
                       float observer_z;
                       float unit_scale;
                       float offset_x;
                       float offset_y;
                       double az, bz, cz, dz;
                       double sum_z;
                       double ax, bx, cx, dx;
                       double sum_x;
                       double ay, by, cy, dy;
                       double sum_y;
                       struct point_state *ps;
                       int old_x;
                       int old_y;
                       double mul;
                       double xf;
                       double yf;
                       int new_x;
                       int new_y;
                       int mov;


#define compute(as,bs,cs,ds,i) \
 az = hs-&gt;hs_ref_az; bz = hs-&gt;hs_ref_bz; cz = hs-&gt;hs_ref_cz; dz = hs-&gt;hs_ref_dz; \
 ax = hs-&gt;hs_ref_ax; bx = hs-&gt;hs_ref_bx; cx = hs-&gt;hs_ref_cx; dx = hs-&gt;hs_ref_dx; \
 ay = hs-&gt;hs_ref_ay; by = hs-&gt;hs_ref_by; cy = hs-&gt;hs_ref_cy; dy = hs-&gt;hs_ref_dy; \
 sum_z = as az bs bz cs cz ds dz; \
 observer_z = hs-&gt;hs_two_observer_z; \
 unit_scale = hs-&gt;hs_unit_scale; \
 sum_x = as ax bs bx cs cx ds dx; \
 sum_y = as ay bs by cs cy ds dy; \
 ps = &amp;hs-&gt;hs_points[i]; \
 mul = unit_scale / (observer_z - sum_z); \
 offset_x = hs-&gt;hs_offset_x; \
 offset_y = hs-&gt;hs_offset_y; \
 old_x = ps-&gt;new_x; \
 old_y = ps-&gt;new_y; \
 xf = sum_x * mul + offset_x; \
 yf = sum_y * mul + offset_y; \
 new_x = (int)(xf+0.5); \
 new_y = (int)(yf+0.5); \
 ps-&gt;old_x = old_x; \
 ps-&gt;old_y = old_y; \
 ps-&gt;new_x = new_x; \
 ps-&gt;new_y = new_y; \
 mov = old_x != new_x || old_y != new_y; \
 moved[i] = mov;

                       compute (-, -, -, -, 0);
                       compute (-, -, -, +, 1);
                       compute (-, -, +, -, 2);
                       compute (-, -, +, +, 3);
                       compute (-, +, -, -, 4);
                       compute (-, +, -, +, 5);
                       compute (-, +, +, -, 6);
                       compute (-, +, +, +, 7);
                       compute (+, -, -, -, 8);
                       compute (+, -, -, +, 9);
                       compute (+, -, +, -, 10);
                       compute (+, -, +, +, 11);
                       compute (+, +, -, -, 12);
                       compute (+, +, -, +, 13);
                       compute (+, +, +, -, 14);
                       compute (+, +, +, +, 15);
               }

skip1:
               icon = hs-&gt;hs_icon;
               if (icon || !(roted | redraw))
                       goto skip2;

               {
                       int i, p_x, p_y;
                       for (i = 0; i &lt; POINT_COUNT; i++) {
                               p_x = hs-&gt;hs_points[i].old_x;
                               p_y = hs-&gt;hs_points[i].old_y;
                               if(p_x == 0 &amp;&amp; p_y == 0)
                                       continue;
                               draw(screen,
                                       rectaddpt(Rect(p_x-24, p_y-24, p_x+24, p_y+24), screen-&gt;r.min),
                                       colors[i], mask, ZP);
                               p_x = hs-&gt;hs_points[i].new_x;
                               p_y = hs-&gt;hs_points[i].new_y;
                               draw(screen,
                                       rectaddpt(Rect(p_x-24, p_y-24, p_x+24, p_y+24), screen-&gt;r.min),
                                       glenda, mask, ZP);
                               }

                       flushimage(display, 1);
               }

skip2:
               stop = hs-&gt;hs_stop;
               roted = 0;
               if (stop)
                       goto skip3;

               roted = 1;

               {
                       double cos_a;
                       double sin_a;
                       double old_u;
                       double old_v;
                       double new_u;
                       double new_v;

                       /* If you get error messages about the following forms, and you think you're
   using an ANSI C conforming compiler, then you're mistaken.  Possibly you're
   mixing an ANSI compiler with a non-ANSI preprocessor, or vice versa.
   Regardless, your system is broken; it's not a bug in this program.
 */

#define rotate(name,dim0,dim1) \
 old_u = hs-&gt;hs_ref_/**/name/**/dim0; \
 old_v = hs-&gt;hs_ref_/**/name/**/dim1; \
 new_u = old_u * cos_a + old_v * sin_a; \
 new_v = old_v * cos_a - old_u * sin_a; \
 hs-&gt;hs_ref_/**/name/**/dim0 = new_u; \
 hs-&gt;hs_ref_/**/name/**/dim1 = new_v;

#define rotates(dim0,dim1) \
 if (hs-&gt;hs_sin_/**/dim0/**/dim1 != 0) { \
   cos_a = hs-&gt;hs_cos_/**/dim0/**/dim1; \
   sin_a = hs-&gt;hs_sin_/**/dim0/**/dim1; \
   rotate(a,dim0,dim1); \
   rotate(b,dim0,dim1); \
   rotate(c,dim0,dim1); \
   rotate(d,dim0,dim1); \
 }

                       rotates (x,y);
                       rotates (x,z);
                       rotates (y,z);
                       rotates (x,w);
                       rotates (y,w);
                       rotates (z,w);
               }

skip3:
               /* stop = hs-&gt;hs_stop; */
               delay = hs-&gt;hs_delay;
               if (stop &amp;&amp; delay &lt; 10)
                       delay = 10;

               frames++;
               if (delay &gt; 0)
                       sleep (delay);
       }
}


static void
check_events (struct hyper_state *hs)
{
       hs-&gt;hs_resize = 0;
       hs-&gt;hs_redraw = 0;

       if(ecanmouse()) {
               m = emouse();
               if(m.buttons&amp;4)
                       if(emenuhit(3, &amp;m, &amp;menu) == 0)  {
                               tend = nsec();
                               print("fps: %uf\n", frames/((tend - tbegin)/1000000000.0));
                               exits(0);
                       }
               if(m.buttons&amp;1)
                       hs-&gt;hs_stop = hs-&gt;hs_stop ? 0 :  1;
               if(m.buttons&amp;2)
                       draw(screen, screen-&gt;r, display-&gt;black, nil, ZP);
       }

}


static void
set_sizes (struct hyper_state *hs, int width, int height)
{
       double observer_z;
       int min_dim;
       double var;
       double offset_x;
       double offset_y;
       double unit_scale;

       observer_z = 0.5 * hs-&gt;hs_two_observer_z;
       min_dim = width &lt; height ? width : height;
       var = sqrt(observer_z * observer_z - 1.0);
       offset_x = 0.5 * (double)(width - 1);
       offset_y = 0.5 * (double)(height - 1);
       unit_scale = 0.4 * min_dim * var;
       hs-&gt;hs_offset_x = (float)offset_x;
       hs-&gt;hs_offset_y = (float)offset_y;
       hs-&gt;hs_unit_scale = (float)unit_scale;
}


/* data */

static const struct line_info line_table[LINE_COUNT] =
{
       { 0, 1, 0, },
       { 0, 2, 0, },
       { 1, 3, 0, },
       { 2, 3, 0, },
       { 4, 5, 1, },
       { 4, 6, 1, },
       { 5, 7, 1, },
       { 6, 7, 1, },
       { 0, 4, 4, },
       { 0, 8, 4, },
       { 4, 12, 4, },
       { 8, 12, 4, },
       { 1, 5, 5, },
       { 1, 9, 5, },
       { 5, 13, 5, },
       { 9, 13, 5, },
       { 2, 6, 6, },
       { 2, 10, 6, },
       { 6, 14, 6, },
       { 10, 14, 6, },
       { 3, 7, 7, },
       { 3, 11, 7, },
       { 7, 15, 7, },
       { 11, 15, 7, },
       { 8, 9, 2, },
       { 8, 10, 2, },
       { 9, 11, 2, },
       { 10, 11, 2, },
       { 12, 13, 3, },
       { 12, 14, 3, },
       { 13, 15, 3, },
       { 14, 15, 3, },
};

void
eresized(int new)
{

       if(new &amp;&amp; getwindow(display, Refnone) &lt; 0) {
               sysfatal("can't reattach to window");
       }

       set_sizes (&amp;hyper_state, Dx(screen-&gt;r), Dy(screen-&gt;r));
       hyper_state.hs_resize = 1;

       draw(screen, screen-&gt;r, display-&gt;black, nil, ZP);

}

void
main(int argc, char **argv)
{
       int i, fd;

       USED(argc, argv);
       srand(time(0)*getpid());


       if(initdraw(nil, nil, "glenda") &lt; 0)
               sysfatal("initdraw failed: %r");

       for(i = 0; i &lt; POINT_COUNT; i++) {
               colors[i] = allocimage(display, Rect(0, 0, 1, 1), screen-&gt;chan, 1,
                       cmap2rgba(nrand(128)+64));
       }

       einit(Emouse);
//      eresized(0);

       fd = open("/lib/face/48x48x4/g/glenda.1", OREAD);
       if(fd &lt; 0)
               sysfatal("cannot open /lib/face/48x48x4/g/glenda.1: %r");

       glenda = readimage(display, fd, 0);
       if(glenda == nil)
               sysfatal("cannot load glenda's image: %r");
       close(fd);

       mask = allocimage(display, Rect(0, 0, 48, 48), glenda-&gt;chan, 1, DCyan);
       if(mask == nil)
               sysfatal("cannot allocate mask: %r");

       draw(mask, mask-&gt;r, display-&gt;white, nil, ZP);
       gendraw(mask, mask-&gt;r, display-&gt;black, ZP, glenda, glenda-&gt;r.min);
       freeimage(glenda);
       glenda = display-&gt;white;

       draw(screen, screen-&gt;r, display-&gt;black, nil, ZP);

       screenhack();
}
<!-- BEGIN TAIL -->
</pre>
</td></tr></table>
</td></tr></table>
<p style="margin-top: 0; margin-bottom: 0.17in"></p>
<p style="line-height: 1.2em; margin-left: 1.00in; text-indent: 0.00in; margin-right: 1.00in; margin-top: 0; margin-bottom: 0; text-align: center;">
<span style="font-size: 10pt"></span></p>
<p style="margin-top: 0; margin-bottom: 0.50in"></p>
<p style="margin-top: 0; margin-bottom: 0.33in"></p>
<center><table border="0"><tr>
<td valign="middle"><a href="http://www.alcatel-lucent.com/"><img border="0" src="/plan9/img/logo_ft.gif" alt="Bell Labs" />
</a></td>
<td valign="middle"><a href="http://www.opensource.org"><img border="0" alt="OSI certified" src="/plan9/img/osi-certified-60x50.gif" />
</a></td>
<td><img style="padding-right: 45px;" alt="Powered by Plan 9" src="/plan9/img/power36.gif" />
</td>
</tr></table></center>
<p style="margin-top: 0; margin-bottom: 0.17in"></p>
<center>
<span style="font-size: 10pt">(<a href="/plan9/">Return to Plan 9 Home Page</a>)</span>
</center>
<p style="margin-top: 0; margin-bottom: 0.17in"></p>
<center><font size=-1>
<span style="font-size: 10pt"><a href="http://www.lucent.com/copyright.html">Copyright</a></span>
<span style="font-size: 10pt">© 2009 Alcatel-Lucent.</span>
<span style="font-size: 10pt">All Rights Reserved.</span>
<br />
<span style="font-size: 10pt">Comments to</span>
<span style="font-size: 10pt"><a href="mailto:[email protected]">[email protected]</a>.</span>
</font></center>
</body>
</html>