--- /dev/null
+/*
+ * Copyright (C) 2008 Thadeu Lima de Souza Cascardo <cascardo@holoscopio.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+
+#include <gtk/gtk.h>
+#include <gdk-pixbuf/gdk-pixbuf.h>
+#include "point.h"
+
+struct ctx
+{
+ GtkWidget *draw;
+ GdkPixbuf *picture;
+ GArray *points;
+ int i;
+ gboolean move;
+};
+
+#define FILENAME "/home/cascardo/fotos/debconf.jpg"
+#define WIDTH 800
+#define HEIGHT 600
+
+gboolean
+queue (gpointer data)
+{
+ struct ctx *ctx;
+ ctx = (struct ctx *) data;
+ gtk_widget_queue_draw (GTK_WIDGET (ctx->draw));
+ ctx->move = TRUE;
+ return FALSE;
+}
+
+gboolean
+expose (GtkWidget *widget, GdkEventExpose *event, gpointer data)
+{
+ GdkPixbuf *screen;
+ struct ctx *ctx;
+ Point point;
+ int w, h;
+ ctx = (struct ctx *) data;
+ gdk_drawable_get_size (GDK_DRAWABLE (event->window), &w, &h);
+ if (ctx->move)
+ ctx->i = (ctx->i >= ctx->points->len) ? 0 : ctx->i + 1;
+ point = g_array_index (ctx->points, Point, ctx->i);
+ screen = gdk_pixbuf_new (GDK_COLORSPACE_RGB, FALSE, 8,
+ event->area.width, event->area.height);
+ gdk_pixbuf_scale (ctx->picture, screen, 0, 0,
+ event->area.width, event->area.height,
+ -point.x + w/2 - event->area.x,
+ -point.y + h/2 - event->area.y,
+ point.rx, point.ry, GDK_INTERP_BILINEAR);
+ gdk_draw_pixbuf (widget->window, NULL, screen, 0, 0,
+ event->area.x, event->area.y,
+ event->area.width, event->area.height,
+ GDK_RGB_DITHER_NONE, 0, 0);
+ gdk_pixbuf_unref (screen);
+ if (point.name)
+ {
+ if (ctx->move)
+ g_timeout_add (3000, queue, ctx);
+ }
+ else
+ {
+ if (ctx->move)
+ g_timeout_add (10, queue, ctx);
+ }
+ ctx->move = FALSE;
+ return FALSE;
+}
+
+#define FPF 40
+
+int
+main (int argc, char **argv)
+{
+ char *filename;
+ GdkColorspace colorspace;
+ gboolean has_alpha;
+ int bits_per_sample;
+ int width, height;
+ GtkWidget *window;
+ struct ctx ctx;
+ gtk_init (&argc, &argv);
+ if (argc < 2)
+ filename = FILENAME;
+ else
+ filename = argv[1];
+ ctx.points = ReadPoints ("pro-gnu");
+ ctx.points = drop_dup_frames (ctx.points, FPF);
+ rescale_points (ctx.points, get_scales (FPF));
+ ctx.picture = gdk_pixbuf_new_from_file (filename, NULL);
+ ctx.i = ctx.points->len;
+ colorspace = gdk_pixbuf_get_colorspace (ctx.picture);
+ has_alpha = gdk_pixbuf_get_has_alpha (ctx.picture);
+ bits_per_sample = gdk_pixbuf_get_bits_per_sample (ctx.picture);
+ width = WIDTH;
+ height = HEIGHT;
+ window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
+ g_signal_connect (G_OBJECT (window), "destroy",
+ G_CALLBACK (gtk_main_quit), NULL);
+ ctx.draw = gtk_drawing_area_new ();
+ gtk_widget_set_size_request (ctx.draw, width, height);
+ gtk_container_add (GTK_CONTAINER (window), ctx.draw);
+ gtk_widget_show_all (window);
+ g_signal_connect (G_OBJECT (ctx.draw), "expose_event",
+ G_CALLBACK (expose), &ctx);
+ g_timeout_add (10, queue, &ctx);
+ gtk_main ();
+ gdk_pixbuf_unref (ctx.picture);
+ return 0;
+}
--- /dev/null
+/*
+ * Copyright (C) 2008 Thadeu Lima de Souza Cascardo <cascardo@holoscopio.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#define _GNU_SOURCE
+#include <glib.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <ctype.h>
+#include <math.h>
+
+#include "point.h"
+
+#define SWAP(x, y) do { \
+ x ^= y; y ^= x; x ^= y; \
+ } while (0)
+
+void
+InsertLine (GArray *points, Point *src, Point *dst)
+{
+ Point rect;
+ int inc, err, thre, swap;
+ int x1, y1, x2, y2;
+ int x, y;
+ rect.name = NULL;
+ err = 0;
+ swap = 0;
+ x1 = src->x;
+ y1 = src->y;
+ x2 = dst->x;
+ y2 = dst->y;
+ inc = y2 - y1;
+ thre = x2 - x1;
+ if (ABS (inc) > ABS (thre))
+ {
+ SWAP (inc, thre);
+ SWAP (x1, y1);
+ SWAP (x2, y2);
+ swap = 1;
+ }
+ for (y = y1, x = x1; (x2 < x1) ? (x >= x2) : (x <= x2); (x2 < x1) ? x-- : x++)
+ {
+ rect.x = (swap ? y : x);
+ rect.y = (swap ? x : y);
+ g_array_append_val (points, rect);
+ err += ABS (inc);
+ if (err >= ABS (thre))
+ {
+ err -= ABS (thre);
+ y += (inc < 0) ? -1 : 1;
+ }
+ }
+}
+
+GArray *
+ReadPoints (char *filename)
+{
+ GArray *points;
+ FILE *file;
+ char *buffer;
+ char *next;
+ size_t len;
+ ssize_t r;
+ int i = 0;
+ Point last;
+ Point rect;
+ file = fopen (filename, "r");
+ points = g_array_new (FALSE, TRUE, sizeof (Point));
+ buffer = NULL;
+ len = 0;
+ rect.x = rect.y = 0;
+ rect.name = NULL;
+ last = rect;
+ while (!feof (file))
+ {
+ r = getline (&buffer, &len, file);
+ buffer[r - 1] = '\0';
+ rect.x = strtol (buffer, &next, 0);
+ rect.y = strtol (next+1, &next, 0);
+ strtol (next, &next, 0);
+ while (isspace (*next)) next++;
+ rect.name = g_strdup (next);
+ if (i > 0)
+ InsertLine (points, &last, &rect);
+ g_array_append_val (points, rect);
+ last = rect;
+ i++;
+ }
+ fclose (file);
+ return points;
+}
+
+GArray *
+drop_dup_frames (GArray *points, int n)
+{
+ GArray *frames;
+ Point *point;
+ Point *next;
+ int i;
+ int j;
+ int inc;
+ int thre;
+ int err;
+ inc = n;
+ frames = g_array_new (FALSE, TRUE, sizeof (Point));
+ for (i = 0; i < points->len;)
+ {
+ j = i + 1;
+ point = next = &(g_array_index (points, Point, j));
+ while (next->name == NULL && j < points->len)
+ {
+ j++;
+ next = &(g_array_index (points, Point, j));
+ }
+ thre = j - i;
+ err = 0;
+ g_array_append_val (frames, g_array_index (points, Point, i));
+ for (; i < j; i++)
+ {
+ err += inc;
+ while (err > thre)
+ {
+ err -= thre;
+ g_array_append_val (frames, g_array_index (points, Point, i));
+ }
+ }
+ }
+ return frames;
+}
+
+GArray *
+get_scales (int n)
+{
+ GArray *scales;
+ double scale;
+ double factor;
+ scales = g_array_new (FALSE, TRUE, sizeof (double));
+ factor = pow (4.0, 1.0/((double) n/2));
+ factor = 1.0/factor;
+ for (scale = 4.00; scale > 1.0 && scales->len < n/2; scale *= factor)
+ scales = g_array_append_val (scales, scale);
+ factor = 1.0/factor;
+ for (scale = 1.0; scale < 4.0 && scales->len < n; scale *= factor)
+ scales = g_array_append_val (scales, scale);
+ return scales;
+}
+
+void
+rescale_points (GArray *points, GArray *scales)
+{
+ Point *point;
+ double scale;
+ int i;
+ for (i = 0; i < points->len; i++)
+ {
+ point = &(g_array_index (points, Point, i));
+ scale = g_array_index (scales, double, (i % scales->len));
+ point->rx = scale;
+ point->ry = scale;
+ point->x *= point->rx;
+ point->y *= point->ry;
+ }
+}
--- /dev/null
+/*
+ * Copyright (C) 2008 Thadeu Lima de Souza Cascardo <cascardo@holoscopio.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+
+#ifndef POINTS_H
+#define POINTS_H
+
+#include <glib.h>
+
+typedef struct
+{
+ int x, y;
+ double rx, ry;
+ char *name;
+} Point;
+
+GArray * ReadPoints (char *);
+void rescale_points (GArray *, GArray *);
+GArray * drop_dup_frames (GArray *, int);
+GArray *get_scales (int);
+
+#endif
--- /dev/null
+/*
+ * Copyright (C) 2008 Thadeu Lima de Souza Cascardo <cascardo@holoscopio.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <cairo.h>
+#include <SDL.h>
+#include <SDL_image.h>
+
+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)
+{
+ 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, double scale)
+{
+ unsigned char *data = NULL;
+ cairo_surface_t *surface = NULL;
+ cairo_t *ctx = NULL;
+ cairo_surface_t *source;
+ SDL_Surface *dest;
+ int w, h;
+ w = image->w * scale;
+ h = image->h * scale;
+ data = malloc (w * h * 4);
+ surface = cairo_image_surface_create_for_data (data, CAIRO_FORMAT_ARGB32,
+ w, h, w * 4);
+ ctx = cairo_create (surface);
+ cairo_scale (ctx, scale, scale);
+ source = CairoFromSDL (image);
+ cairo_set_source_surface (ctx, source, 0, 0);
+ cairo_paint (ctx);
+ cairo_surface_destroy (source);
+ dest = CairoToSDL (surface);
+ cairo_surface_destroy (surface);
+ cairo_destroy (ctx);
+ return dest;
+}
+
+SDL_Surface *
+CairoScale (SDL_Surface *image, double scale)
+{
+ SDL_Surface *newfmt;
+ SDL_Surface *slice;
+ SDL_Surface *scaled_image;
+ newfmt = SDL_CreateRGBSurface (SDL_SWSURFACE, 1, 1,
+ 32,
+ 0x00ff0000,
+ 0x0000ff00,
+ 0x000000ff,
+ 0xff000000);
+ slice = SDL_ConvertSurface (image, newfmt->format, SDL_SWSURFACE);
+ SDL_FreeSurface (newfmt);
+ scaled_image = CairoTarget (slice, scale);
+ SDL_FreeSurface (slice);
+ return scaled_image;
+}