f279449d03ee3ce1a1dfd9fc34da31fe2ccad2ab
[cascardo/movie.git] / movie.c
1 /*
2  *  Copyright (C) 2008  Thadeu Lima de Souza Cascardo <cascardo@holoscopio.com>
3  *
4  *  This program is free software; you can redistribute it and/or modify
5  *  it under the terms of the GNU General Public License as published by
6  *  the Free Software Foundation; either version 2 of the License, or
7  *  (at your option) any later version.
8  *
9  *  This program is distributed in the hope that it will be useful,
10  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
11  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  *  GNU General Public License for more details.
13  *
14  *  You should have received a copy of the GNU General Public License along
15  *  with this program; if not, write to the Free Software Foundation, Inc.,
16  *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
17  */
18
19 #define WIDTH 800
20 #define HEIGHT 600
21
22 #include <stdio.h>
23 #include <stdlib.h>
24 #include <SDL.h>
25 #include <SDL_image.h>
26
27 #define SWAP(x, y) do { \
28         x ^= y; y ^= x; x ^= y; \
29         } while (0)
30
31 #define ABS(x) ((x) < 0 ? -(x) : (x))
32
33 #define IS_CENTER(cx, cy, x, y) \
34         ((x + WIDTH/2 == cx) && (y + HEIGHT/2 == cy))
35
36 SDL_Rect *points;
37 int psize;
38
39 void
40 ReadPoints (char *filename)
41 {
42   FILE *file;
43   char *buffer;
44   char *next;
45   size_t len;
46   int i;
47   file = fopen (filename, "r");
48   fscanf (file, "%d\n", &psize);
49   points = malloc (sizeof (SDL_Rect) * psize);
50   if (points == NULL)
51     abort ();
52   buffer = NULL;
53   len = 0;
54   for (i = 0; i < psize; i++)
55   {
56     getline (&buffer, &len, file);
57     points[i].x = strtol (buffer, &next, 0);
58     points[i].y = strtol (next+1, NULL, 0);
59   }
60   fclose (file);
61 }
62
63 SDL_Rect *
64 GetNextPoint (void)
65 {
66   static SDL_Rect rect = {0, 0, WIDTH, HEIGHT};
67   static int cur = -1;
68   static int inc, err, thre, swap;
69   static int x1, y1, x2, y2;
70   static int x, y;
71   int next;
72   next = (cur + 1) % psize;
73   if (IS_CENTER (points[next].x, points[next].y, rect.x, rect.y) || cur == -1)
74   {
75     cur = next;
76     next = (cur + 1) % psize;
77     err = 0;
78     swap = 0;
79     x1 = points[cur].x;
80     y1 = points[cur].y;
81     x2 = points[next].x;
82     y2 = points[next].y;
83     inc = y2 - y1;
84     thre = x2 - x1;
85     if (ABS (inc) > ABS (thre))
86     {
87       SWAP (inc, thre);
88       SWAP (x1, y1);
89       SWAP (x2, y2);
90       swap = 1;
91     }
92     x = x1;
93     y = y1;
94   }
95   rect.x = (swap ? y : x) - WIDTH/2;
96   rect.y = (swap ? x : y) - HEIGHT/2;
97   (x2 < x1) ? x-- : x++;
98   err += ABS (inc);
99   if (err >= ABS (thre))
100   {
101     err -= ABS (thre);
102     y += (inc < 0) ? -1 : 1;
103   }
104   return &rect;
105 }
106
107 void
108 ShowPoint (SDL_Surface *screen, SDL_Surface *image, SDL_Rect *rect)
109 {
110   SDL_BlitSurface (image, rect, screen, NULL);
111   SDL_UpdateRect (screen, 0, 0, 0, 0);
112 }
113
114 Uint32
115 ShowNext (Uint32 interval, void *data)
116 {
117   SDL_UserEvent event;
118   event.type = SDL_USEREVENT;
119   event.code = 0;
120   SDL_PushEvent ((SDL_Event *) &event);
121   return 33;
122 }
123
124 int
125 main (int argc, char **argv)
126 {
127   SDL_Surface *screen;
128   SDL_Surface *image;
129   SDL_Event event;
130   ReadPoints ("pro-gnu");
131   SDL_Init (SDL_INIT_VIDEO | SDL_INIT_TIMER);
132   screen = SDL_SetVideoMode (800, 600, 32, SDL_HWSURFACE | SDL_DOUBLEBUF);
133   image = IMG_Load ("/home/cascardo/fotos/debconf.jpg");
134   SDL_AddTimer (0, ShowNext, NULL);
135   while (SDL_WaitEvent (&event))
136   {
137     if (event.type == SDL_KEYDOWN)
138       break;
139     else if (event.type == SDL_USEREVENT)
140       ShowPoint (screen, image, GetNextPoint ());
141   }
142   SDL_FreeSurface (image);
143   SDL_Quit ();
144   free (points);
145   return 0;
146 }