libcaca  0.99.beta19
About: libcaca is a graphics library that outputs text instead of pixels, so that it can work on older video cards or text terminals (something like an advanced AAlib library).
  Fossies Dox: libcaca-0.99.beta19.tar.gz  ("inofficial" and yet experimental doxygen-generated source code documentation)  

cacademo.c
Go to the documentation of this file.
1 /*
2  * cacademo various demo effects for libcaca
3  * Copyright (c) 1998 Michele Bini <mibin@tin.it>
4  * 2003-2006 Jean-Yves Lamoureux <jylam@lnxscene.org>
5  * 2004-2012 Sam Hocevar <sam@hocevar.net>
6  * All Rights Reserved
7  *
8  * This program is free software. It comes without any warranty, to
9  * the extent permitted by applicable law. You can redistribute it
10  * and/or modify it under the terms of the Do What the Fuck You Want
11  * to Public License, Version 2, as published by Sam Hocevar. See
12  * http://www.wtfpl.net/ for more details.
13  */
14 
15 #include "config.h"
16 
17 #if !defined(__KERNEL__)
18 # include <stdio.h>
19 # include <stdlib.h>
20 # include <string.h>
21 # include <math.h>
22 # ifndef M_PI
23 # define M_PI 3.14159265358979323846
24 # endif
25 #endif
26 
27 #include "caca.h"
28 
30 
31 void transition(caca_canvas_t *, int, int);
32 void plasma(enum action, caca_canvas_t *);
33 void metaballs(enum action, caca_canvas_t *);
34 void moire(enum action, caca_canvas_t *);
35 void langton(enum action, caca_canvas_t *);
36 void matrix(enum action, caca_canvas_t *);
37 void rotozoom(enum action, caca_canvas_t *);
38 
39 void (*fn[])(enum action, caca_canvas_t *) =
40 {
41  plasma,
42  metaballs,
43  moire,
44  /*langton,*/
45  matrix,
46  rotozoom,
47 };
48 #define DEMOS (sizeof(fn)/sizeof(*fn))
49 
50 #define DEMO_FRAMES caca_rand(500, 1000)
51 #define TRANSITION_FRAMES 40
52 
53 #define TRANSITION_COUNT 5
54 #define TRANSITION_CIRCLE 0
55 #define TRANSITION_STAR 1
56 #define TRANSITION_SQUARE 2
57 #define TRANSITION_VLINES 3
58 #define TRANSITION_HLINES 4
59 
60 /* Common macros for dither-based demos */
61 #define XSIZ 256
62 #define YSIZ 256
63 
64 /* Global variables */
65 static int frame = 0;
66 
67 int main(int argc, char **argv)
68 {
69  static caca_display_t *dp;
70  static caca_canvas_t *frontcv, *backcv, *mask;
71 
72  int demo, next = -1, paused = 0, next_transition = DEMO_FRAMES;
73  unsigned int i;
74  int tmode = caca_rand(0, TRANSITION_COUNT);
75 
76  /* Set up two canvases, a mask, and attach a display to the front one */
77  frontcv = caca_create_canvas(0, 0);
78  backcv = caca_create_canvas(0, 0);
79  mask = caca_create_canvas(0, 0);
80 
81  dp = caca_create_display(frontcv);
82  if(!dp)
83  return 1;
84 
86  caca_get_canvas_height(frontcv));
88  caca_get_canvas_height(frontcv));
89 
90  caca_set_display_time(dp, 20000);
91 
92  /* Initialise all demos' lookup tables */
93  for(i = 0; i < DEMOS; i++)
94  fn[i](PREPARE, frontcv);
95 
96  /* Choose a demo at random */
97  demo = caca_rand(0, DEMOS);
98  fn[demo](INIT, frontcv);
99 
100  for(;;)
101  {
102  /* Handle events */
103  caca_event_t ev;
105  | CACA_EVENT_QUIT, &ev, 0))
106  {
108  goto end;
109 
110  switch(caca_get_event_key_ch(&ev))
111  {
112  case CACA_KEY_ESCAPE:
113  case CACA_KEY_CTRL_C:
114  case CACA_KEY_CTRL_Z:
115  goto end;
116  case ' ':
117  paused = !paused;
118  break;
119  case '\r':
120  if(next == -1)
121  next_transition = frame;
122  break;
123  }
124  }
125 
126  /* Resize the spare canvas, just in case the main one changed */
128  caca_get_canvas_height(frontcv));
130  caca_get_canvas_height(frontcv));
131 
132  if(paused)
133  goto _paused;
134 
135  /* Update demo's data */
136  fn[demo](UPDATE, frontcv);
137 
138  /* Handle transitions */
139  if(frame == next_transition)
140  {
141  next = caca_rand(0, DEMOS);
142  if(next == demo)
143  next = (next + 1) % DEMOS;
144  fn[next](INIT, backcv);
145  }
146  else if(frame == next_transition + TRANSITION_FRAMES)
147  {
148  fn[demo](FREE, frontcv);
149  demo = next;
150  next = -1;
151  next_transition = frame + DEMO_FRAMES;
152  tmode = caca_rand(0, TRANSITION_COUNT);
153  }
154 
155  if(next != -1)
156  fn[next](UPDATE, backcv);
157 
158  frame++;
159 _paused:
160  /* Render main demo's canvas */
161  fn[demo](RENDER, frontcv);
162 
163  /* If a transition is on its way, render it */
164  if(next != -1)
165  {
166  fn[next](RENDER, backcv);
168  caca_clear_canvas(mask);
170  transition(mask, tmode,
171  100 * (frame - next_transition) / TRANSITION_FRAMES);
172  caca_blit(frontcv, 0, 0, backcv, mask);
173  }
174 
176  if(frame < 100)
177  caca_put_str(frontcv, caca_get_canvas_width(frontcv) - 30,
178  caca_get_canvas_height(frontcv) - 2,
179  " -=[ Powered by libcaca ]=- ");
181  }
182 end:
183  if(next != -1)
184  fn[next](FREE, frontcv);
185  fn[demo](FREE, frontcv);
186 
188  caca_free_canvas(mask);
189  caca_free_canvas(backcv);
190  caca_free_canvas(frontcv);
191 
192  return 0;
193 }
194 
195 /* Transitions */
196 void transition(caca_canvas_t *mask, int tmode, int completed)
197 {
198  static float const star[] =
199  {
200  0.000000, -1.000000,
201  0.308000, -0.349000,
202  0.992000, -0.244000,
203  0.500000, 0.266000,
204  0.632000, 0.998000,
205  0.008000, 0.659000,
206  -0.601000, 0.995000,
207  -0.496000, 0.275000,
208  -0.997000, -0.244000,
209  -0.313000, -0.349000
210  };
211  static float star_rot[sizeof(star)/sizeof(*star)];
212 
213 
214  static float const square[] =
215  {
216  -1, -1,
217  1, -1,
218  1, 1,
219  -1, 1
220  };
221  static float square_rot[sizeof(square)/sizeof(*square)];
222 
223  float mulx = 0.0075f * completed * caca_get_canvas_width(mask);
224  float muly = 0.0075f * completed * caca_get_canvas_height(mask);
225  int w2 = caca_get_canvas_width(mask) / 2;
226  int h2 = caca_get_canvas_height(mask) / 2;
227  float angle = (0.0075f * completed * 360) * 3.14 / 180, x, y;
228  unsigned int i;
229  int w = caca_get_canvas_width(mask);
230  int h = caca_get_canvas_height(mask);
231 
232  switch(tmode)
233  {
234  case TRANSITION_SQUARE:
235  /* Compute rotated coordinates */
236  for(i = 0; i < (sizeof(square) / sizeof(*square)) / 2; i++)
237  {
238  x = square[i * 2];
239  y = square[i * 2 + 1];
240 
241  square_rot[i * 2] = x * cos(angle) - y * sin(angle);
242  square_rot[i * 2 + 1] = y * cos(angle) + x * sin(angle);
243  }
244 
245  mulx *= 1.8;
246  muly *= 1.8;
247  caca_fill_triangle(mask,
248  square_rot[0*2] * mulx + w2, square_rot[0*2+1] * muly + h2, \
249  square_rot[1*2] * mulx + w2, square_rot[1*2+1] * muly + h2, \
250  square_rot[2*2] * mulx + w2, square_rot[2*2+1] * muly + h2, '#');
251  caca_fill_triangle(mask,
252  square_rot[0*2] * mulx + w2, square_rot[0*2+1] * muly + h2, \
253  square_rot[2*2] * mulx + w2, square_rot[2*2+1] * muly + h2, \
254  square_rot[3*2] * mulx + w2, square_rot[3*2+1] * muly + h2, '#');
255  break;
256 
257 
258  case TRANSITION_STAR:
259  /* Compute rotated coordinates */
260  for(i = 0; i < (sizeof(star) / sizeof(*star)) / 2; i++)
261  {
262  x = star[i * 2];
263  y = star[i * 2 + 1];
264 
265  star_rot[i * 2] = x * cos(angle) - y * sin(angle);
266  star_rot[i * 2 + 1] = y * cos(angle) + x * sin(angle);
267  }
268 
269  mulx *= 1.8;
270  muly *= 1.8;
271 
272 #define DO_TRI(a, b, c) \
273  caca_fill_triangle(mask, \
274  star_rot[(a)*2] * mulx + w2, star_rot[(a)*2+1] * muly + h2, \
275  star_rot[(b)*2] * mulx + w2, star_rot[(b)*2+1] * muly + h2, \
276  star_rot[(c)*2] * mulx + w2, star_rot[(c)*2+1] * muly + h2, '#')
277  DO_TRI(0, 1, 9);
278  DO_TRI(1, 2, 3);
279  DO_TRI(3, 4, 5);
280  DO_TRI(5, 6, 7);
281  DO_TRI(7, 8, 9);
282  DO_TRI(9, 1, 5);
283  DO_TRI(9, 5, 7);
284  DO_TRI(1, 3, 5);
285  break;
286 
287  case TRANSITION_CIRCLE:
288  caca_fill_ellipse(mask, w2, h2, mulx, muly, '#');
289  break;
290 
291  case TRANSITION_VLINES:
292  for(i = 0; i < 8; i++)
293  {
294  int z = ((i & 1) ? w : (-w)/2) * (100 - completed) / 100;
295  caca_fill_box(mask, i * w / 8, z , (w / 8) + 1, z + h, '#');
296  }
297  break;
298 
299  case TRANSITION_HLINES:
300 
301  for(i = 0; i < 6; i++)
302  {
303  int z = ((i & 1) ? w : (-w)/2) * (100 - completed) / 100;
304  caca_fill_box(mask, z, i * h / 6, z + w, (h / 6) + 1, '#');
305  }
306  break;
307  }
308 }
309 
310 /* The plasma effect */
311 #define TABLEX (XSIZ * 2)
312 #define TABLEY (YSIZ * 2)
313 static uint8_t table[TABLEX * TABLEY];
314 
315 static void do_plasma(uint8_t *,
316  double, double, double, double, double, double);
317 
319 {
320  static caca_dither_t *dither;
321  static uint8_t *screen;
322  static uint32_t red[256], green[256], blue[256], alpha[256];
323  static double r[3], R[6];
324 
325  int i, x, y;
326 
327  switch(action)
328  {
329  case PREPARE:
330  /* Fill various tables */
331  for(i = 0 ; i < 256; i++)
332  red[i] = green[i] = blue[i] = alpha[i] = 0;
333 
334  for(i = 0; i < 3; i++)
335  r[i] = (double)(caca_rand(1, 1000)) / 60000 * M_PI;
336 
337  for(i = 0; i < 6; i++)
338  R[i] = (double)(caca_rand(1, 1000)) / 10000;
339 
340  for(y = 0 ; y < TABLEY ; y++)
341  for(x = 0 ; x < TABLEX ; x++)
342  {
343  double tmp = (((double)((x - (TABLEX / 2)) * (x - (TABLEX / 2))
344  + (y - (TABLEX / 2)) * (y - (TABLEX / 2))))
345  * (M_PI / (TABLEX * TABLEX + TABLEY * TABLEY)));
346 
347  table[x + y * TABLEX] = (1.0 + sin(12.0 * sqrt(tmp))) * 256 / 6;
348  }
349  break;
350 
351  case INIT:
352  screen = malloc(XSIZ * YSIZ * sizeof(uint8_t));
353  dither = caca_create_dither(8, XSIZ, YSIZ, XSIZ, 0, 0, 0, 0);
354  break;
355 
356  case UPDATE:
357  for(i = 0 ; i < 256; i++)
358  {
359  double z = ((double)i) / 256 * 6 * M_PI;
360 
361  red[i] = (1.0 + sin(z + r[1] * frame)) / 2 * 0xfff;
362  blue[i] = (1.0 + cos(z + r[0] * (frame + 100))) / 2 * 0xfff;
363  green[i] = (1.0 + cos(z + r[2] * (frame + 200))) / 2 * 0xfff;
364  }
365 
366  /* Set the palette */
367  caca_set_dither_palette(dither, red, green, blue, alpha);
368 
369  do_plasma(screen,
370  (1.0 + sin(((double)frame) * R[0])) / 2,
371  (1.0 + sin(((double)frame) * R[1])) / 2,
372  (1.0 + sin(((double)frame) * R[2])) / 2,
373  (1.0 + sin(((double)frame) * R[3])) / 2,
374  (1.0 + sin(((double)frame) * R[4])) / 2,
375  (1.0 + sin(((double)frame) * R[5])) / 2);
376  break;
377 
378  case RENDER:
379  caca_dither_bitmap(cv, 0, 0,
382  dither, screen);
383  break;
384 
385  case FREE:
386  free(screen);
387  caca_free_dither(dither);
388  break;
389  }
390 }
391 
392 static void do_plasma(uint8_t *pixels, double x_1, double y_1,
393  double x_2, double y_2, double x_3, double y_3)
394 {
395  unsigned int X1 = x_1 * (TABLEX / 2),
396  Y1 = y_1 * (TABLEY / 2),
397  X2 = x_2 * (TABLEX / 2),
398  Y2 = y_2 * (TABLEY / 2),
399  X3 = x_3 * (TABLEX / 2),
400  Y3 = y_3 * (TABLEY / 2);
401  unsigned int y;
402  uint8_t * t1 = table + X1 + Y1 * TABLEX,
403  * t2 = table + X2 + Y2 * TABLEX,
404  * t3 = table + X3 + Y3 * TABLEX;
405 
406  for(y = 0; y < YSIZ; y++)
407  {
408  unsigned int x;
409  uint8_t * tmp = pixels + y * YSIZ;
410  unsigned int ty = y * TABLEX, tmax = ty + XSIZ;
411  for(x = 0; ty < tmax; ty++, tmp++)
412  tmp[0] = t1[ty] + t2[ty] + t3[ty];
413  }
414 }
415 
416 /* The metaball effect */
417 #define METASIZE (XSIZ/2)
418 #define METABALLS 12
419 #define CROPBALL 200 /* Colour index where to crop balls */
420 static uint8_t metaball[METASIZE * METASIZE];
421 
422 static void create_ball(void);
423 static void draw_ball(uint8_t *, unsigned int, unsigned int);
424 
426 {
427  static caca_dither_t *caca_dither;
428  static uint8_t *screen;
429  static uint32_t r[256], g[256], b[256], a[256];
430  static float dd[METABALLS], di[METABALLS], dj[METABALLS], dk[METABALLS];
431  static unsigned int x[METABALLS], y[METABALLS];
432  static float i = 10.0, j = 17.0, k = 11.0;
433  static double offset[360 + 80];
434  static unsigned int angleoff;
435 
436  int n, angle;
437 
438  switch(action)
439  {
440  case PREPARE:
441  /* Make the palette eatable by libcaca */
442  for(n = 0; n < 256; n++)
443  r[n] = g[n] = b[n] = a[n] = 0x0;
444  r[255] = g[255] = b[255] = 0xfff;
445 
446  /* Generate ball sprite */
447  create_ball();
448 
449  for(n = 0; n < METABALLS; n++)
450  {
451  dd[n] = caca_rand(0, 100);
452  di[n] = (float)caca_rand(500, 4000) / 6000.0;
453  dj[n] = (float)caca_rand(500, 4000) / 6000.0;
454  dk[n] = (float)caca_rand(500, 4000) / 6000.0;
455  }
456 
457  angleoff = caca_rand(0, 360);
458 
459  for(n = 0; n < 360 + 80; n++)
460  offset[n] = 1.0 + sin((double)(n * M_PI / 60));
461  break;
462 
463  case INIT:
464  screen = malloc(XSIZ * YSIZ * sizeof(uint8_t));
465  /* Create a libcaca dither smaller than our pixel buffer, so that we
466  * display only the interesting part of it */
468  XSIZ, 0, 0, 0, 0);
469  break;
470 
471  case UPDATE:
472  angle = (frame + angleoff) % 360;
473 
474  /* Crop the palette */
475  for(n = CROPBALL; n < 255; n++)
476  {
477  int t1, t2, t3;
478  double c1 = offset[angle];
479  double c2 = offset[angle + 40];
480  double c3 = offset[angle + 80];
481 
482  t1 = n < 0x40 ? 0 : n < 0xc0 ? (n - 0x40) * 0x20 : 0xfff;
483  t2 = n < 0xe0 ? 0 : (n - 0xe0) * 0x80;
484  t3 = n < 0x40 ? n * 0x40 : 0xfff;
485 
486  r[n] = (c1 * t1 + c2 * t2 + c3 * t3) / 4;
487  g[n] = (c1 * t2 + c2 * t3 + c3 * t1) / 4;
488  b[n] = (c1 * t3 + c2 * t1 + c3 * t2) / 4;
489  }
490 
491  /* Set the palette */
493 
494  /* Silly paths for our balls */
495  for(n = 0; n < METABALLS; n++)
496  {
497  float u = di[n] * i + dj[n] * j + dk[n] * sin(di[n] * k);
498  float v = dd[n] + di[n] * j + dj[n] * k + dk[n] * sin(dk[n] * i);
499  u = sin(i + u * 2.1) * (1.0 + sin(u));
500  v = sin(j + v * 1.9) * (1.0 + sin(v));
501  x[n] = (XSIZ - METASIZE) / 2 + u * (XSIZ - METASIZE) / 4;
502  y[n] = (YSIZ - METASIZE) / 2 + v * (YSIZ - METASIZE) / 4;
503  }
504 
505  i += 0.011;
506  j += 0.017;
507  k += 0.019;
508 
509  memset(screen, 0, XSIZ * YSIZ);
510 
511  for(n = 0; n < METABALLS; n++)
512  draw_ball(screen, x[n], y[n]);
513  break;
514 
515  case RENDER:
516  caca_dither_bitmap(cv, 0, 0,
519  caca_dither, screen + (METASIZE / 2) * (1 + XSIZ));
520  break;
521 
522  case FREE:
523  free(screen);
525  break;
526  }
527 }
528 
529 static void create_ball(void)
530 {
531  int x, y;
532  float distance;
533 
534  for(y = 0; y < METASIZE; y++)
535  for(x = 0; x < METASIZE; x++)
536  {
537  distance = ((METASIZE/2) - x) * ((METASIZE/2) - x)
538  + ((METASIZE/2) - y) * ((METASIZE/2) - y);
539  distance = sqrt(distance) * 64 / METASIZE;
540  metaball[x + y * METASIZE] = distance > 15 ? 0 : (255 - distance) * 15;
541  }
542 }
543 
544 static void draw_ball(uint8_t *screen, unsigned int bx, unsigned int by)
545 {
546  unsigned int color;
547  unsigned int i, e = 0;
548  unsigned int b = (by * XSIZ) + bx;
549 
550  for(i = 0; i < METASIZE * METASIZE; i++)
551  {
552  color = screen[b] + metaball[i];
553 
554  if(color > 255)
555  color = 255;
556 
557  screen[b] = color;
558  if(e == METASIZE)
559  {
560  e = 0;
561  b += XSIZ - METASIZE;
562  }
563  b++;
564  e++;
565  }
566 }
567 
568 /* The moiré effect */
569 #define DISCSIZ (XSIZ*2)
570 #define DISCTHICKNESS (XSIZ*15/40)
571 static uint8_t disc[DISCSIZ * DISCSIZ];
572 
573 static void put_disc(uint8_t *, int, int);
574 static void draw_line(int, int, char);
575 
577 {
578  static caca_dither_t *dither;
579  static uint8_t *screen;
580  static float d[6];
581  static uint32_t red[256], green[256], blue[256], alpha[256];
582 
583  int i, x, y;
584 
585  switch(action)
586  {
587  case PREPARE:
588  /* Fill various tables */
589  for(i = 0 ; i < 256; i++)
590  red[i] = green[i] = blue[i] = alpha[i] = 0;
591 
592  for(i = 0; i < 6; i++)
593  d[i] = ((float)caca_rand(50, 70)) / 1000.0;
594 
595  red[0] = green[0] = blue[0] = 0x777;
596  red[1] = green[1] = blue[1] = 0xfff;
597 
598  /* Fill the circle */
599  for(i = DISCSIZ * 2; i > 0; i -= DISCTHICKNESS)
600  {
601  int t, dx, dy;
602 
603  for(t = 0, dx = 0, dy = i; dx <= dy; dx++)
604  {
605  draw_line(dx / 3, dy / 3, (i / DISCTHICKNESS) % 2);
606  draw_line(dy / 3, dx / 3, (i / DISCTHICKNESS) % 2);
607 
608  t += t > 0 ? dx - dy-- : dx;
609  }
610  }
611 
612  break;
613 
614  case INIT:
615  screen = malloc(XSIZ * YSIZ * sizeof(uint8_t));
616  dither = caca_create_dither(8, XSIZ, YSIZ, XSIZ, 0, 0, 0, 0);
617  break;
618 
619  case UPDATE:
620  memset(screen, 0, XSIZ * YSIZ);
621 
622  /* Set the palette */
623  red[0] = 0.5 * (1 + sin(d[0] * (frame + 1000))) * 0xfff;
624  green[0] = 0.5 * (1 + cos(d[1] * frame)) * 0xfff;
625  blue[0] = 0.5 * (1 + cos(d[2] * (frame + 3000))) * 0xfff;
626 
627  red[1] = 0.5 * (1 + sin(d[3] * (frame + 2000))) * 0xfff;
628  green[1] = 0.5 * (1 + cos(d[4] * frame + 5.0)) * 0xfff;
629  blue[1] = 0.5 * (1 + cos(d[5] * (frame + 4000))) * 0xfff;
630 
631  caca_set_dither_palette(dither, red, green, blue, alpha);
632 
633  /* Draw circles */
634  x = cos(d[0] * (frame + 1000)) * 128.0 + (XSIZ / 2);
635  y = sin(0.11 * frame) * 128.0 + (YSIZ / 2);
636  put_disc(screen, x, y);
637 
638  x = cos(0.13 * frame + 2.0) * 64.0 + (XSIZ / 2);
639  y = sin(d[1] * (frame + 2000)) * 64.0 + (YSIZ / 2);
640  put_disc(screen, x, y);
641  break;
642 
643  case RENDER:
644  caca_dither_bitmap(cv, 0, 0,
647  dither, screen);
648  break;
649 
650  case FREE:
651  free(screen);
652  caca_free_dither(dither);
653  break;
654  }
655 }
656 
657 static void put_disc(uint8_t *screen, int x, int y)
658 {
659  char *src = ((char*)disc) + (DISCSIZ / 2 - x) + (DISCSIZ / 2 - y) * DISCSIZ;
660  int i, j;
661 
662  for(j = 0; j < YSIZ; j++)
663  for(i = 0; i < XSIZ; i++)
664  {
665  screen[i + XSIZ * j] ^= src[i + DISCSIZ * j];
666  }
667 }
668 
669 static void draw_line(int x, int y, char color)
670 {
671  if(x == 0 || y == 0 || y > DISCSIZ / 2)
672  return;
673 
674  if(x > DISCSIZ / 2)
675  x = DISCSIZ / 2;
676 
677  memset(disc + (DISCSIZ / 2) - x + DISCSIZ * ((DISCSIZ / 2) - y),
678  color, 2 * x - 1);
679  memset(disc + (DISCSIZ / 2) - x + DISCSIZ * ((DISCSIZ / 2) + y - 1),
680  color, 2 * x - 1);
681 }
682 
683 /* Langton ant effect */
684 #define ANTS 15
685 #define ITER 2
686 
688 {
689  static char gradient[] =
690  {
691  ' ', ' ', '.', '.', ':', ':', 'x', 'x',
692  'X', 'X', '&', '&', 'W', 'W', '@', '@',
693  };
694  static int steps[][2] = { { 0, 1 }, { 1, 0 }, { 0, -1 }, { -1, 0 } };
695  static uint8_t *screen;
696  static int width, height;
697  static int ax[ANTS], ay[ANTS], dir[ANTS];
698 
699  int i, a, x, y;
700 
701  switch(action)
702  {
703  case PREPARE:
704  width = caca_get_canvas_width(cv);
705  height = caca_get_canvas_height(cv);
706  for(i = 0; i < ANTS; i++)
707  {
708  ax[i] = caca_rand(0, width);
709  ay[i] = caca_rand(0, height);
710  dir[i] = caca_rand(0, 4);
711  }
712  break;
713 
714  case INIT:
715  screen = malloc(width * height);
716  memset(screen, 0, width * height);
717  break;
718 
719  case UPDATE:
720  for(i = 0; i < ITER; i++)
721  {
722  for(x = 0; x < width * height; x++)
723  {
724  uint8_t p = screen[x];
725  if((p & 0x0f) > 1)
726  screen[x] = p - 1;
727  }
728 
729  for(a = 0; a < ANTS; a++)
730  {
731  uint8_t p = screen[ax[a] + width * ay[a]];
732 
733  if(p & 0x0f)
734  {
735  dir[a] = (dir[a] + 1) % 4;
736  screen[ax[a] + width * ay[a]] = a << 4;
737  }
738  else
739  {
740  dir[a] = (dir[a] + 3) % 4;
741  screen[ax[a] + width * ay[a]] = (a << 4) | 0x0f;
742  }
743  ax[a] = (width + ax[a] + steps[dir[a]][0]) % width;
744  ay[a] = (height + ay[a] + steps[dir[a]][1]) % height;
745  }
746  }
747  break;
748 
749  case RENDER:
750  for(y = 0; y < height; y++)
751  {
752  for(x = 0; x < width; x++)
753  {
754  uint8_t p = screen[x + width * y];
755 
756  if(p & 0x0f)
758  else
760  caca_put_char(cv, x, y, gradient[p & 0x0f]);
761  }
762  }
763  break;
764 
765  case FREE:
766  free(screen);
767  break;
768  }
769 }
770 
771 /* Matrix effect */
772 #define MAXDROPS 500
773 #define MINLEN 15
774 #define MAXLEN 30
775 
777 {
778  static struct drop
779  {
780  int x, y, speed, len;
781  char str[MAXLEN];
782  }
783  drop[MAXDROPS];
784 
785  int w, h, i, j;
786 
787  switch(action)
788  {
789  case PREPARE:
790  for(i = 0; i < MAXDROPS; i++)
791  {
792  drop[i].x = caca_rand(0, 1000);
793  drop[i].y = caca_rand(0, 1000);
794  drop[i].speed = 5 + caca_rand(0, 30);
795  drop[i].len = MINLEN + caca_rand(0, (MAXLEN - MINLEN));
796  for(j = 0; j < MAXLEN; j++)
797  drop[i].str[j] = caca_rand('0', 'z');
798  }
799  break;
800 
801  case INIT:
802  break;
803 
804  case UPDATE:
807 
808  for(i = 0; i < MAXDROPS && i < (w * h / 32); i++)
809  {
810  drop[i].y += drop[i].speed;
811  if(drop[i].y > 1000)
812  {
813  drop[i].y -= 1000;
814  drop[i].x = caca_rand(0, 1000);
815  }
816  }
817  break;
818 
819  case RENDER:
822 
825 
826  for(i = 0; i < MAXDROPS && i < (w * h / 32); i++)
827  {
828  int x, y;
829 
830  x = drop[i].x * w / 1000 / 2 * 2;
831  y = drop[i].y * (h + MAXLEN) / 1000;
832 
833  for(j = 0; j < drop[i].len; j++)
834  {
835  unsigned int fg;
836 
837  if(j < 2)
838  fg = CACA_WHITE;
839  else if(j < drop[i].len / 4)
840  fg = CACA_LIGHTGREEN;
841  else if(j < drop[i].len * 4 / 5)
842  fg = CACA_GREEN;
843  else
844  fg = CACA_DARKGRAY;
846 
847  caca_put_char(cv, x, y - j,
848  drop[i].str[(y - j) % drop[i].len]);
849  }
850  }
851  break;
852 
853  case FREE:
854  break;
855  }
856 }
857 
858 /* Rotozoom effect */
859 #define TEXTURE_SIZE 256
860 #define TABLE_SIZE 65536
861 
862 /* 24:8 Fixed point stuff */
863 #define PRECISION 8
864 
865 #define FMUL(a, b) (((a)*(b))>>PRECISION)
866 #define TOFIX(d) ((int)( (d)*(double)(1<<PRECISION) ))
867 #define TOINT(a) (a>>PRECISION);
868 
869 #include "texture.h"
870 
871 void rotozoom(enum action action, caca_canvas_t *canvas)
872 {
873  static uint32_t screen[XSIZ * YSIZ];
874  static int cos_tab[TABLE_SIZE], sin_tab[TABLE_SIZE];
875  static int y_tab[TEXTURE_SIZE];
876 
877  static caca_dither_t *dither;
878  uint32_t *p;
879  static int alphaF, tF;
880  int scaleF;
881 
882  /* register is quite a bad idea on CISC, but not on RISC */
883  register unsigned int x, y;
884  register unsigned int xxF, yyF, uF, vF, uF_, vF_;
885  register unsigned int vu, vv;
886 
887  switch(action)
888  {
889  case PREPARE:
890  for(x = 0; x < TABLE_SIZE; x++)
891  {
892  cos_tab[x] = TOFIX(cos(x * (360.0f / (float)TABLE_SIZE)));
893  sin_tab[x] = TOFIX(sin(x * (360.0f / (float)TABLE_SIZE)));
894  }
895  for(x = 0; x < TEXTURE_SIZE; x++)
896  y_tab[x] = x * TEXTURE_SIZE; /* start of lines offsets */
897  break;
898 
899  case INIT:
900  dither = caca_create_dither(32, XSIZ, YSIZ, XSIZ * 4,
901  0x00FF0000,
902  0x0000FF00,
903  0x000000FF,
904  0x00000000);
905  break;
906 
907  case UPDATE:
908  alphaF += 4;
909  tF += 3;
910  scaleF = FMUL(sin_tab[tF & 0xFFFF], TOFIX(3)) + (TOFIX(4));
911  xxF = FMUL(cos_tab[(alphaF) & 0xFFFF], scaleF);
912  yyF = FMUL(sin_tab[(alphaF) & 0xFFFF], scaleF);
913  uF = vF = 0;
914  uF_ = vF_ = 0;
915  p = screen;
916 
917  for(y = YSIZ; y--;)
918  {
919  for(x = XSIZ; x--;)
920  {
921  uF += xxF;
922  vF += yyF;
923 
924  vu = TOINT(uF);
925  vv = TOINT(vF);
926  vu &= 0xFF; /* ARM doesn't like */
927  vv &= 0xFF; /* chars as local vars */
928 
929  *p++ = texture256x256[vu + y_tab[vv]];
930  }
931 
932  uF = uF_ -= yyF;
933  vF = vF_ += xxF;
934  }
935  break;
936 
937  case RENDER:
938  caca_dither_bitmap(canvas, 0, 0,
939  caca_get_canvas_width(canvas),
940  caca_get_canvas_height(canvas),
941  dither, screen);
942  break;
943 
944  case FREE:
945  caca_free_dither(dither);
946  break;
947  }
948 }
949 
caca_create_dither
caca_dither_t * caca_create_dither(int, int, int, int, uint32_t, uint32_t, uint32_t, uint32_t)
Create an internal dither object.
Definition: dither.c:261
CACA_LIGHTGREEN
Definition: caca.h:81
caca_dither
Definition: dither.c:116
ANTS
#define ANTS
Definition: cacademo.c:684
YSIZ
#define YSIZ
Definition: cacademo.c:62
TRANSITION_STAR
#define TRANSITION_STAR
Definition: cacademo.c:55
caca_blit
int caca_blit(caca_canvas_t *, int, int, caca_canvas_t const *, caca_canvas_t const *)
Blit a canvas onto another one.
Definition: string.c:455
caca_create_display
caca_display_t * caca_create_display(caca_canvas_t *cv)
Attach a caca graphical context to a caca canvas.
Definition: caca.c:68
caca_set_dither_palette
int caca_set_dither_palette(caca_dither_t *, uint32_t r[], uint32_t g[], uint32_t b[], uint32_t a[])
Set the palette of an 8bpp dither object.
Definition: dither.c:372
y
static int y
Definition: cacadraw.c:27
METABALLS
#define METABALLS
Definition: cacademo.c:418
metaballs
void metaballs(enum action, caca_canvas_t *)
Definition: cacademo.c:425
caca_set_display_time
int caca_set_display_time(caca_display_t *, int)
Set the refresh delay.
Definition: graphics.c:100
TRANSITION_SQUARE
#define TRANSITION_SQUARE
Definition: cacademo.c:56
texture256x256
static const uint32_t texture256x256[]
Definition: texture.h:13
g
int g
Definition: cacaview.c:60
create_ball
static void create_ball(void)
Definition: cacademo.c:529
ITER
#define ITER
Definition: cacademo.c:685
M_PI
#define M_PI
Definition: cacademo.c:23
caca_event
Handling of user events.
Definition: caca.h:129
main
int main(int argc, char **argv)
Definition: cacademo.c:67
caca_create_canvas
caca_canvas_t * caca_create_canvas(int, int)
Initialise a libcaca canvas.
Definition: canvas.c:54
caca_display
Definition: caca_internals.h:167
metaball
static uint8_t metaball[(256/2) *(256/2)]
Definition: cacademo.c:420
caca_free_canvas
int caca_free_canvas(caca_canvas_t *)
Free a libcaca canvas.
Definition: canvas.c:308
caca_get_event_type
enum caca_event_type caca_get_event_type(caca_event_t const *)
Return an event's type.
Definition: event.c:202
caca_get_canvas_height
int caca_get_canvas_height(caca_canvas_t const *)
Get the canvas height.
Definition: canvas.c:253
CACA_EVENT_QUIT
Definition: caca.h:117
do_plasma
static void do_plasma(uint8_t *, double, double, double, double, double, double)
Definition: cacademo.c:392
put_disc
static void put_disc(uint8_t *, int, int)
Definition: cacademo.c:657
caca_get_canvas_width
int caca_get_canvas_width(caca_canvas_t const *)
Get the canvas width.
Definition: canvas.c:239
action
action
Definition: cacademo.c:29
caca_fill_ellipse
#define caca_fill_ellipse(x, y, z, t, c)
Definition: caca0.h:165
caca_rand
#define caca_rand(a, b)
Definition: caca0.h:180
DISCTHICKNESS
#define DISCTHICKNESS
Definition: cacademo.c:570
CACA_LIGHTGRAY
Definition: caca.h:78
TRANSITION_COUNT
#define TRANSITION_COUNT
Definition: cacademo.c:53
dy
float dy
Definition: cacaview.c:59
DEMOS
#define DEMOS
Definition: cacademo.c:48
fn
void(* fn[])(enum action, caca_canvas_t *)
Definition: cacademo.c:39
CACA_WHITE
Definition: caca.h:86
caca_put_str
int caca_put_str(caca_canvas_t *, int, int, char const *)
Print a string.
Definition: string.c:254
CACA_KEY_CTRL_Z
Definition: caca.h:191
FREE
Definition: cacademo.c:29
METASIZE
#define METASIZE
Definition: cacademo.c:417
matrix
void matrix(enum action, caca_canvas_t *)
Definition: cacademo.c:776
CACA_GREEN
Definition: caca.h:73
UPDATE
Definition: cacademo.c:29
CROPBALL
#define CROPBALL
Definition: cacademo.c:419
draw_ball
static void draw_ball(uint8_t *, unsigned int, unsigned int)
Definition: cacademo.c:544
CACA_KEY_ESCAPE
Definition: caca.h:192
cv
caca_canvas_t * cv
Definition: cacaview.c:45
TABLEY
#define TABLEY
Definition: cacademo.c:312
frame
static int frame
Definition: cacademo.c:65
caca_refresh_display
int caca_refresh_display(caca_display_t *)
Flush pending changes and redraw the screen.
Definition: graphics.c:146
distance
static int distance(uint16_t, uint16_t)
Definition: sortchars.c:192
transition
void transition(caca_canvas_t *, int, int)
Definition: cacademo.c:196
FMUL
#define FMUL(a, b)
Definition: cacademo.c:865
plasma
void plasma(enum action, caca_canvas_t *)
Definition: cacademo.c:318
MAXLEN
#define MAXLEN
Definition: cacademo.c:774
caca_fill_triangle
#define caca_fill_triangle(x, y, z, t, u, v, c)
Definition: caca0.h:177
caca_put_char
int caca_put_char(caca_canvas_t *, int, int, uint32_t)
Print an ASCII or Unicode character.
Definition: string.c:120
caca_free_display
int caca_free_display(caca_display_t *dp)
Detach a caca graphical context from a caca backend context.
Definition: caca.c:238
table
static uint8_t table[(256 *2) *(256 *2)]
Definition: cacademo.c:313
TOINT
#define TOINT(a)
Definition: cacademo.c:867
disc
static uint8_t disc[(256 *2) *(256 *2)]
Definition: cacademo.c:571
CACA_KEY_CTRL_C
Definition: caca.h:168
TRANSITION_FRAMES
#define TRANSITION_FRAMES
Definition: cacademo.c:51
TRANSITION_CIRCLE
#define TRANSITION_CIRCLE
Definition: cacademo.c:54
CACA_BLUE
Definition: caca.h:72
TABLE_SIZE
#define TABLE_SIZE
Definition: cacademo.c:860
rotozoom
void rotozoom(enum action, caca_canvas_t *)
Definition: cacademo.c:871
MINLEN
#define MINLEN
Definition: cacademo.c:773
CACA_BLACK
Definition: caca.h:71
RENDER
Definition: cacademo.c:29
CACA_DARKGRAY
Definition: caca.h:79
DISCSIZ
#define DISCSIZ
Definition: cacademo.c:569
TRANSITION_VLINES
#define TRANSITION_VLINES
Definition: cacademo.c:57
texture.h
caca_dither_bitmap
int caca_dither_bitmap(caca_canvas_t *, int, int, int, int, caca_dither_t const *, void const *)
Dither a bitmap on the canvas.
Definition: dither.c:940
TABLEX
#define TABLEX
Definition: cacademo.c:311
caca_set_color_ansi
int caca_set_color_ansi(caca_canvas_t *cv, uint8_t fg, uint8_t bg)
Set the default colour pair for text (ANSI version).
Definition: attr.c:234
caca_set_canvas_size
int caca_set_canvas_size(caca_canvas_t *, int, int)
Resize a canvas.
Definition: canvas.c:212
caca.h
The libcaca public header.
TOFIX
#define TOFIX(d)
Definition: cacademo.c:866
config.h
DO_TRI
#define DO_TRI(a, b, c)
caca_get_event
#define caca_get_event(x)
Definition: caca0.h:136
draw_line
static void draw_line(int, int, char)
Definition: cacademo.c:669
caca_clear_canvas
int caca_clear_canvas(caca_canvas_t *)
Clear the canvas.
Definition: string.c:374
moire
void moire(enum action, caca_canvas_t *)
Definition: cacademo.c:576
CACA_EVENT_KEY_PRESS
Definition: caca.h:111
langton
void langton(enum action, caca_canvas_t *)
Definition: cacademo.c:687
TEXTURE_SIZE
#define TEXTURE_SIZE
Definition: cacademo.c:859
INIT
Definition: cacademo.c:29
caca_free_dither
int caca_free_dither(caca_dither_t *)
Free the memory associated with a dither.
Definition: dither.c:1209
DEMO_FRAMES
#define DEMO_FRAMES
Definition: cacademo.c:50
dx
float dx
Definition: cacaview.c:59
dp
caca_display_t * dp
Definition: cacaview.c:45
XSIZ
#define XSIZ
Definition: cacademo.c:61
MAXDROPS
#define MAXDROPS
Definition: cacademo.c:772
caca_get_event_key_ch
int caca_get_event_key_ch(caca_event_t const *)
Return a key press or key release event's value.
Definition: event.c:219
caca_fill_box
#define caca_fill_box(x, y, z, t, c)
Definition: caca0.h:171
caca_canvas
Definition: caca_internals.h:47
x
static int x
Definition: cacadraw.c:27
TRANSITION_HLINES
#define TRANSITION_HLINES
Definition: cacademo.c:58
PREPARE
Definition: cacademo.c:29