#define WIDTH 800
#define HEIGHT 600
+#define HBORDER 32
+#define VBORDER 8
+#define RX (0.5)
+#define RY (0.5)
+
+#define STOP_INTERVAL (2*1000)
+#define FPS (100)
+#define FRAME_INTERVAL (1000/(FPS))
#include <stdio.h>
#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+#include <cairo.h>
#include <SDL.h>
#include <SDL_image.h>
+#include <SDL_ttf.h>
#define SWAP(x, y) do { \
x ^= y; y ^= x; x ^= y; \
#define IS_CENTER(cx, cy, x, y) \
((x + WIDTH/2 == cx) && (y + HEIGHT/2 == cy))
+TTF_Font *font;
+
SDL_Rect *points;
+char **names;
+int cur = -1;
int psize;
+int stop = 0;
void
ReadPoints (char *filename)
char *buffer;
char *next;
size_t len;
+ ssize_t r;
int i;
file = fopen (filename, "r");
fscanf (file, "%d\n", &psize);
points = malloc (sizeof (SDL_Rect) * psize);
- if (points == NULL)
+ names = malloc (sizeof (char *) * psize);
+ if (points == NULL || names == NULL)
abort ();
buffer = NULL;
len = 0;
for (i = 0; i < psize; i++)
{
- getline (&buffer, &len, file);
+ r = getline (&buffer, &len, file);
+ buffer[r - 1] = '\0';
points[i].x = strtol (buffer, &next, 0);
- points[i].y = strtol (next+1, NULL, 0);
+ points[i].y = strtol (next+1, &next, 0);
+ strtol (next, &next, 0);
+ while (isspace (*next)) next++;
+ names[i] = strdup (next);
}
fclose (file);
}
-SDL_Rect *
+SDL_Rect
GetNextPoint (void)
{
static SDL_Rect rect = {0, 0, WIDTH, HEIGHT};
- static int cur = -1;
static int inc, err, thre, swap;
static int x1, y1, x2, y2;
static int x, y;
next = (cur + 1) % psize;
if ((points[next].x == rect.x && points[next].y == rect.y) || cur == -1)
{
+ stop = 1;
cur = next;
next = (cur + 1) % psize;
err = 0;
err -= ABS (thre);
y += (inc < 0) ? -1 : 1;
}
- return ▭
+ return rect;
}
void
-ShowPoint (SDL_Surface *screen, SDL_Surface *image, SDL_Rect *rect)
+ShowPoint (SDL_Surface *screen, SDL_Surface *image)
{
- SDL_BlitSurface (image, rect, screen, NULL);
+ SDL_BlitSurface (image, NULL, screen, NULL);
SDL_UpdateRect (screen, 0, 0, 0, 0);
}
-Uint32
-ShowNext (Uint32 interval, void *data)
+cairo_surface_t *
+CairoFromSDL (SDL_Surface *surface)
+{
+ return cairo_image_surface_create_for_data (surface->pixels,
+ CAIRO_FORMAT_ARGB32,
+ surface->w, surface->h,
+ surface->pitch);
+}
+
+SDL_Surface *
+CairoToSDL (cairo_surface_t *surface)
{
- SDL_UserEvent event;
- event.type = SDL_USEREVENT;
- event.code = 0;
- SDL_PushEvent ((SDL_Event *) &event);
- return 33;
+ return SDL_CreateRGBSurfaceFrom (cairo_image_surface_get_data (surface),
+ cairo_image_surface_get_width (surface),
+ cairo_image_surface_get_height (surface),
+ 32,
+ cairo_image_surface_get_stride (surface),
+ 0x00ff0000, 0x0000ff00, 0x000000ff,
+ 0xff000000);
+}
+
+SDL_Surface *
+CairoTarget (SDL_Surface *image)
+{
+ static unsigned char *data = NULL;
+ static cairo_surface_t *surface = NULL;
+ static cairo_t *ctx = NULL;
+ cairo_surface_t *source;
+ static double rx = 1.0, ry = 1.0;
+ if (data == NULL && surface == NULL && ctx == NULL)
+ {
+ data = malloc (WIDTH * HEIGHT * 4);
+ surface = cairo_image_surface_create_for_data (data, CAIRO_FORMAT_ARGB32,
+ WIDTH, HEIGHT, WIDTH * 4);
+ ctx = cairo_create (surface);
+ }
+ cairo_scale (ctx, 1.0/rx, 1.0/ry);
+ rx = (double) WIDTH / (double) image->w;
+ ry = (double) HEIGHT / (double) image->h;
+ cairo_scale (ctx, rx, ry);
+ source = CairoFromSDL (image);
+ cairo_set_source_surface (ctx, source, 0, 0);
+ cairo_paint (ctx);
+ cairo_surface_destroy (source);
+ return CairoToSDL (surface);
+}
+
+SDL_Surface *
+GetNextImage (SDL_Surface *image)
+{
+ SDL_Surface *slice;
+ SDL_Rect center;
+ SDL_Surface *scale;
+ SDL_Surface *text;
+ SDL_Rect box;
+ SDL_Color Yellow = { 255, 255, 0, 0};
+ static double rx = RX, ry = RY, factor = 0.5;
+ if (rx < 0.25)
+ {
+ factor = 1.05;
+ }
+ if (rx > 2)
+ {
+ factor = 0.95238095238095233;
+ }
+ rx *= factor;
+ ry *= factor;
+ center = GetNextPoint ();
+ slice = SDL_CreateRGBSurface (SDL_SWSURFACE, WIDTH*rx, HEIGHT*ry,
+ 32,
+ 0x00ff0000, 0x0000ff00, 0x000000ff, 0xff000000);
+ center.x -= (WIDTH/2) * rx;
+ center.y -= (HEIGHT/2) * ry;
+ center.w *= rx;
+ center.h *= ry;
+ SDL_BlitSurface (image, ¢er, slice, NULL);
+ SDL_UpdateRect (slice, 0, 0, 0, 0);
+ scale = CairoTarget (slice);
+ SDL_FreeSurface (slice);
+ if (stop)
+ {
+ text = TTF_RenderUTF8_Solid (font, names[cur], Yellow);
+ box.w = text->w + HBORDER;
+ box.h = text->h + VBORDER;
+ box.x = (WIDTH - text->w - HBORDER) / 2;
+ box.y = HEIGHT - (text->h + 32 + VBORDER/2);
+ SDL_FillRect (scale, &box, SDL_MapRGB (scale->format, 0, 0, 0));
+ box.x += HBORDER/2;
+ box.y += VBORDER/2;
+ box.w -= HBORDER;
+ box.h -= VBORDER;
+ SDL_BlitSurface (text, NULL, scale, &box);
+ SDL_FreeSurface (text);
+ }
+ SDL_UpdateRect (scale, 0, 0, 0, 0);
+ return scale;
}
int
{
SDL_Surface *screen;
SDL_Surface *image;
+ SDL_Surface *slice;
SDL_Event event;
+ Uint32 now, last;
+ int i;
ReadPoints ("pro-gnu");
SDL_Init (SDL_INIT_VIDEO | SDL_INIT_TIMER);
- screen = SDL_SetVideoMode (800, 600, 32, SDL_HWSURFACE | SDL_DOUBLEBUF);
+ TTF_Init ();
+ font = TTF_OpenFont ("/usr/share/fonts/truetype/ttf-dejavu/DejaVuSans.ttf", 48);
+ screen = SDL_SetVideoMode (WIDTH, HEIGHT, 32, SDL_HWSURFACE | SDL_DOUBLEBUF);
image = IMG_Load ("/home/cascardo/fotos/debconf.jpg");
- SDL_AddTimer (0, ShowNext, NULL);
- while (SDL_WaitEvent (&event))
+ last = SDL_GetTicks ();
+ while (1)
{
- if (event.type == SDL_KEYDOWN)
- break;
- else if (event.type == SDL_USEREVENT)
- ShowPoint (screen, image, GetNextPoint ());
+ if (SDL_PollEvent (&event))
+ {
+ if (event.type == SDL_KEYDOWN)
+ break;
+ }
+ now = SDL_GetTicks ();
+ /* skip */
+ while (!stop && now > last + FRAME_INTERVAL)
+ {
+ last += FRAME_INTERVAL;
+ GetNextPoint ();
+ }
+ slice = GetNextImage (image);
+ ShowPoint (screen, slice);
+ SDL_FreeSurface (slice);
+ if (stop)
+ {
+ stop = 0;
+ SDL_Delay (STOP_INTERVAL);
+ last = SDL_GetTicks ();
+ }
+ else
+ {
+ SDL_Delay (FRAME_INTERVAL - (now - last));
+ }
}
SDL_FreeSurface (image);
+ TTF_CloseFont (font);
+ TTF_Quit ();
SDL_Quit ();
free (points);
+ for (i = 0; i < psize; i++)
+ free (names[i]);
+ free (names);
return 0;
}