summaryrefslogtreecommitdiff
path: root/savers/floaters.c.orig
diff options
context:
space:
mode:
Diffstat (limited to 'savers/floaters.c.orig')
-rw-r--r--savers/floaters.c.orig1256
1 files changed, 0 insertions, 1256 deletions
diff --git a/savers/floaters.c.orig b/savers/floaters.c.orig
deleted file mode 100644
index 1fd84f5..0000000
--- a/savers/floaters.c.orig
+++ /dev/null
@@ -1,1256 +0,0 @@
-/*
- * Copyright (C) 2005 Ray Strode <[email protected]>,
- * Matthias Clasen <[email protected]>,
- * Søren Sandmann <[email protected]>
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser 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
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
- * 02111-1307, USA.
- *
- * Originally written by: Ray Strode <[email protected]>
- *
- * Later contributions by: Matthias Clasen <[email protected]>
- * Søren Sandmann <[email protected]>
- */
-
-#include "config.h"
-
-#include <math.h>
-#include <stdlib.h>
-#include <sysexits.h>
-#include <time.h>
-
-#include <glib.h>
-#include <glib/gi18n.h>
-
-#include <gdk/gdk.h>
-#include <gdk/gdkx.h>
-
-#include <gtk/gtk.h>
-
-#include "gs-theme-window.h"
-
-#ifndef trunc
-#define trunc(x) (((x) > 0.0) ? floor((x)) : -floor(-(x)))
-#endif
-
-#ifndef OPTIMAL_FRAME_RATE
-#define OPTIMAL_FRAME_RATE (25.0)
-#endif
-
-#ifndef STAT_PRINT_FREQUENCY
-#define STAT_PRINT_FREQUENCY (2000)
-#endif
-
-#ifndef FLOATER_MAX_SIZE
-#define FLOATER_MAX_SIZE (128.0)
-#endif
-
-#ifndef FLOATER_MIN_SIZE
-#define FLOATER_MIN_SIZE (16.0)
-#endif
-#ifndef FLOATER_DEFAULT_COUNT
-#define FLOATER_DEFAULT_COUNT (5)
-#endif
-
-#ifndef SMALL_ANGLE
-#define SMALL_ANGLE (0.025 * G_PI)
-#endif
-
-#ifndef BIG_ANGLE
-#define BIG_ANGLE (0.125 * G_PI)
-#endif
-
-#ifndef GAMMA
-#define GAMMA 2.2
-#endif
-
-static gboolean should_show_paths = FALSE;
-static gboolean should_do_rotations = FALSE;
-static gboolean should_print_stats = FALSE;
-static gint max_floater_count = FLOATER_DEFAULT_COUNT;
-static gchar *geometry = NULL;
-static gchar **filenames = NULL;
-
-static GOptionEntry options[] = {
- {"show-paths", 'p', 0, G_OPTION_ARG_NONE, &should_show_paths,
- N_("Show paths that images follow"), NULL},
-
- {"do-rotations", 'r', 0, G_OPTION_ARG_NONE, &should_do_rotations,
- N_("Occasionally rotate images as they move"), NULL},
-
- {"print-stats", 's', 0, G_OPTION_ARG_NONE, &should_print_stats,
- N_("Print out frame rate and other statistics"), NULL},
-
- {"number-of-images", 'n', 0, G_OPTION_ARG_INT, &max_floater_count,
- N_("The maximum number of images to keep on screen"), N_("MAX_IMAGES")},
-
- {"geometry", 0, 0, G_OPTION_ARG_STRING, &geometry,
- N_("The initial size and position of window"), N_("WIDTHxHEIGHT+X+Y")},
-
- {G_OPTION_REMAINING, 0, 0, G_OPTION_ARG_FILENAME_ARRAY, &filenames,
- N_("The source image to use"), NULL},
-
- {NULL}
-};
-
-
-typedef struct _Point Point;
-typedef struct _Path Path;
-typedef struct _Rectangle Rectangle;
-typedef struct _ScreenSaverFloater ScreenSaverFloater;
-typedef struct _CachedSource CachedSource;
-typedef struct _ScreenSaver ScreenSaver;
-
-struct _Point
-{
- gdouble x, y;
-};
-
-struct _Path
-{
- Point start_point;
- Point start_control_point;
- Point end_control_point;
- Point end_point;
-
- gdouble x_linear_coefficient,
- y_linear_coefficient;
-
- gdouble x_quadratic_coefficient,
- y_quadratic_coefficient;
-
- gdouble x_cubic_coefficient,
- y_cubic_coefficient;
-
- gdouble duration;
-};
-
-struct _CachedSource
-{
- cairo_pattern_t *pattern;
- gint width, height;
-};
-
-struct _Rectangle
-{
- Point top_left_point;
- Point bottom_right_point;
-};
-
-struct _ScreenSaverFloater
-{
- GdkRectangle bounds;
-
- Point start_position;
- Point position;
-
- gdouble scale;
- gdouble opacity;
-
- Path *path;
- gdouble path_start_time;
- gdouble path_start_scale;
- gdouble path_end_scale;
-
- gdouble angle;
- gdouble angle_increment;
-};
-
-struct _ScreenSaver
-{
- GtkWidget *drawing_area;
- Rectangle canvas_rectangle;
- GHashTable *cached_sources;
-
- char *filename;
-
- gdouble first_update_time;
-
- gdouble last_calculated_stats_time,
- current_calculated_stats_time;
- gint update_count, frame_count;
-
- gdouble updates_per_second;
- gdouble frames_per_second;
-
- guint state_update_timeout_id;
- guint stats_update_timeout_id;
-
- GList *floaters;
- gint max_floater_count;
-
- guint should_do_rotations: 1;
- guint should_show_paths : 1;
- guint draw_ops_pending : 1;
-};
-
-static Path *path_new (Point *start_point,
- Point *start_control_point,
- Point *end_control_point,
- Point *end_point,
- gdouble duration);
-static void path_free (Path *path);
-
-static ScreenSaverFloater *screen_saver_floater_new (ScreenSaver *screen_saver,
- Point *position,
- gdouble scale);
-static void screen_saver_floater_free (ScreenSaver *screen_saver,
- ScreenSaverFloater *floater);
-static gboolean screen_saver_floater_is_off_canvas (ScreenSaver *screen_saver,
- ScreenSaverFloater *floater);
-static gboolean screen_saver_floater_should_bubble_up (ScreenSaver *screen_saver,
- ScreenSaverFloater *floater,
- gdouble performance_ratio,
- gdouble *duration);
-static gboolean screen_saver_floater_should_come_on_screen (ScreenSaver *screen_saver,
- ScreenSaverFloater *floater,
- gdouble performance_ratio,
- gdouble *duration);
-static Point screen_saver_floater_get_position_from_time (ScreenSaver *screen_saver,
- ScreenSaverFloater *floater,
- gdouble time);
-static gdouble screen_saver_floater_get_scale_from_time (ScreenSaver *screen_saver,
- ScreenSaverFloater *floater,
- gdouble time);
-static gdouble screen_saver_floater_get_angle_from_time (ScreenSaver *screen_saver,
- ScreenSaverFloater *floater,
- gdouble time);
-
-static Path *screen_saver_floater_create_path_to_on_screen (ScreenSaver *screen_saver,
- ScreenSaverFloater *floater,
- gdouble duration);
-static Path *screen_saver_floater_create_path_to_bubble_up (ScreenSaver *screen_saver,
- ScreenSaverFloater *floater,
- gdouble duration);
-static Path *screen_saver_floater_create_path_to_random_point (ScreenSaver *screen_saver,
- ScreenSaverFloater *floater,
- gdouble duration);
-static Path *screen_saver_floater_create_path (ScreenSaver *screen_saver,
- ScreenSaverFloater *floater);
-static void screen_saver_floater_update_state (ScreenSaver *screen_saver,
- ScreenSaverFloater *floater,
- gdouble time);
-
-static gboolean screen_saver_floater_do_draw (ScreenSaver *screen_saver,
- ScreenSaverFloater *floater,
- cairo_t *context);
-
-static CachedSource *cached_source_new (cairo_pattern_t *pattern,
- gint width,
- gint height);
-static void cached_source_free (CachedSource *source);
-
-static ScreenSaver *screen_saver_new (GtkDrawingArea *drawing_area,
- const gchar *filename,
- gint max_floater_count,
- gboolean should_do_rotations,
- gboolean should_show_paths);
-static void screen_saver_free (ScreenSaver *screen_saver);
-static gdouble screen_saver_get_timestamp (ScreenSaver *screen_saver);
-static void screen_saver_get_initial_state (ScreenSaver *screen_saver);
-static void screen_saver_update_state (ScreenSaver *screen_saver,
- gdouble time);
-static gboolean screen_saver_do_update_state (ScreenSaver *screen_saver);
-static gboolean screen_saver_do_update_stats (ScreenSaver *screen_saver);
-static gdouble screen_saver_get_updates_per_second (ScreenSaver *screen_saver);
-static gdouble screen_saver_get_frames_per_second (ScreenSaver *screen_saver);
-static gdouble screen_saver_get_image_cache_usage (ScreenSaver *screen_saver);
-static void screen_saver_create_floaters (ScreenSaver *screen_saver);
-static void screen_saver_destroy_floaters (ScreenSaver *screen_saver);
-static void screen_saver_on_size_allocate (ScreenSaver *screen_saver,
- GtkAllocation *allocation);
-static void screen_saver_on_expose_event (ScreenSaver *screen_saver,
- GdkEventExpose *event);
-static gboolean do_print_screen_saver_stats (ScreenSaver *screen_saver);
-static GdkPixbuf *gamma_correct (const GdkPixbuf *input_pixbuf);
-
-static CachedSource*
-cached_source_new (cairo_pattern_t *pattern,
- gint width,
- gint height)
-{
- CachedSource *source;
-
- source = g_new (CachedSource, 1);
- source->pattern = cairo_pattern_reference (pattern);
- source->width = width;
- source->height = height;
-
- return source;
-}
-
-static void
-cached_source_free (CachedSource *source)
-{
- if (source == NULL)
- return;
-
- cairo_pattern_destroy (source->pattern);
-
- g_free (source);
-}
-
-static Path *
-path_new (Point *start_point,
- Point *start_control_point,
- Point *end_control_point,
- Point *end_point,
- gdouble duration)
-{
- Path *path;
-
- path = g_new (Path, 1);
- path->start_point = *start_point;
- path->start_control_point = *start_control_point;
- path->end_control_point = *end_control_point;
- path->end_point = *end_point;
- path->duration = duration;
-
- /* we precompute the coefficients to the cubic bezier curve here
- * so that we don't have to do it repeatedly later The equation is:
- *
- * B(t) = A * t^3 + B * t^2 + C * t + start_point
- */
- path->x_linear_coefficient = 3 * (start_control_point->x - start_point->x);
- path->x_quadratic_coefficient = 3 * (end_control_point->x -
- start_control_point->x) -
- path->x_linear_coefficient;
- path->x_cubic_coefficient = end_point->x - start_point->x -
- path->x_linear_coefficient -
- path->x_quadratic_coefficient;
-
- path->y_linear_coefficient = 3 * (start_control_point->y - start_point->y);
- path->y_quadratic_coefficient = 3 * (end_control_point->y -
- start_control_point->y) -
- path->y_linear_coefficient;
- path->y_cubic_coefficient = end_point->y - start_point->y -
- path->y_linear_coefficient -
- path->y_quadratic_coefficient;
- return path;
-}
-
-static void
-path_free (Path *path)
-{
- g_free (path);
-}
-
-static ScreenSaverFloater*
-screen_saver_floater_new (ScreenSaver *screen_saver,
- Point *position,
- gdouble scale)
-{
- ScreenSaverFloater *floater;
-
- floater = g_new (ScreenSaverFloater, 1);
- floater->bounds.width = 0;
- floater->start_position = *position;
- floater->position = *position;
- floater->scale = scale;
- floater->opacity = pow (scale, 1.0 / GAMMA);
- floater->path = NULL;
- floater->path_start_time = 0.0;
- floater->path_start_scale = 1.0;
- floater->path_end_scale = 0.0;
-
- floater->angle = 0.0;
- floater->angle_increment = 0.0;
-
- return floater;
-}
-
-void
-screen_saver_floater_free (ScreenSaver *screen_saver,
- ScreenSaverFloater *floater)
-{
- if (floater == NULL)
- return;
-
- path_free (floater->path);
-
- g_free (floater);
-}
-
-static gboolean
-screen_saver_floater_is_off_canvas (ScreenSaver *screen_saver,
- ScreenSaverFloater *floater)
-{
- if ((floater->position.x < screen_saver->canvas_rectangle.top_left_point.x) ||
- (floater->position.x > screen_saver->canvas_rectangle.bottom_right_point.x) ||
- (floater->position.y < screen_saver->canvas_rectangle.top_left_point.y) ||
- (floater->position.y > screen_saver->canvas_rectangle.bottom_right_point.y))
- return TRUE;
-
- return FALSE;
-}
-
-static gboolean
-screen_saver_floater_should_come_on_screen (ScreenSaver *screen_saver,
- ScreenSaverFloater *floater,
- gdouble performance_ratio,
- gdouble *duration)
-{
-
- if (!screen_saver_floater_is_off_canvas (screen_saver, floater))
- return FALSE;
-
- if ((abs (performance_ratio - .5) >= G_MINDOUBLE) &&
- (g_random_double () > .5))
- {
- if (duration)
- *duration = g_random_double_range (3.0, 7.0);
-
- return TRUE;
- }
-
- return FALSE;
-}
-
-static gboolean
-screen_saver_floater_should_bubble_up (ScreenSaver *screen_saver,
- ScreenSaverFloater *floater,
- gdouble performance_ratio,
- gdouble *duration)
-{
-
- if ((performance_ratio < .5) && (g_random_double () > .5))
- {
- if (duration)
- *duration = performance_ratio * 30.0;
-
- return TRUE;
- }
-
- if ((floater->scale < .3) && (g_random_double () > .6))
- {
- if (duration)
- *duration = 30.0;
-
- return TRUE;
- }
-
- return FALSE;
-}
-
-static Point
-screen_saver_floater_get_position_from_time (ScreenSaver *screen_saver,
- ScreenSaverFloater *floater,
- gdouble time)
-{
- Point point;
-
- time = time / floater->path->duration;
-
- point.x = floater->path->x_cubic_coefficient * (time * time * time) +
- floater->path->x_quadratic_coefficient * (time * time) +
- floater->path->x_linear_coefficient * (time) +
- floater->path->start_point.x;
- point.y = floater->path->y_cubic_coefficient * (time * time * time) +
- floater->path->y_quadratic_coefficient * (time * time) +
- floater->path->y_linear_coefficient * (time) +
- floater->path->start_point.y;
-
- return point;
-}
-
-static gdouble
-screen_saver_floater_get_scale_from_time (ScreenSaver *screen_saver,
- ScreenSaverFloater *floater,
- gdouble time)
-{
- gdouble completion_ratio, total_scale_growth, new_scale;
-
- completion_ratio = time / floater->path->duration;
- total_scale_growth = (floater->path_end_scale - floater->path_start_scale);
- new_scale = floater->path_start_scale + total_scale_growth * completion_ratio;
-
- return CLAMP (new_scale, 0.0, 1.0);
-}
-
-static gdouble
-screen_saver_floater_get_angle_from_time (ScreenSaver *screen_saver,
- ScreenSaverFloater *floater,
- gdouble time)
-{
- gdouble completion_ratio;
- gdouble total_rotation;
-
- completion_ratio = time / floater->path->duration;
- total_rotation = floater->angle_increment * floater->path->duration;
-
- return floater->angle + total_rotation * completion_ratio;
-}
-
-static Path *
-screen_saver_floater_create_path_to_on_screen (ScreenSaver *screen_saver,
- ScreenSaverFloater *floater,
- gdouble duration)
-{
- Point start_position, end_position, start_control_point, end_control_point;
- start_position = floater->position;
-
- end_position.x = g_random_double_range (.25, .75) *
- (screen_saver->canvas_rectangle.top_left_point.x +
- screen_saver->canvas_rectangle.bottom_right_point.x);
- end_position.y = g_random_double_range (.25, .75) *
- (screen_saver->canvas_rectangle.top_left_point.y +
- screen_saver->canvas_rectangle.bottom_right_point.y);
-
- start_control_point.x = start_position.x + .9 * (end_position.x - start_position.x);
- start_control_point.y = start_position.y + .9 * (end_position.y - start_position.y);
-
- end_control_point.x = start_position.x + 1.0 * (end_position.x - start_position.x);
- end_control_point.y = start_position.y + 1.0 * (end_position.y - start_position.y);
-
- return path_new (&start_position, &start_control_point, &end_control_point,
- &end_position, duration);
-}
-
-static Path *
-screen_saver_floater_create_path_to_bubble_up (ScreenSaver *screen_saver,
- ScreenSaverFloater *floater,
- gdouble duration)
-{
- Point start_position, end_position, start_control_point, end_control_point;
-
- start_position = floater->position;
- end_position.x = start_position.x;
- end_position.y = screen_saver->canvas_rectangle.top_left_point.y - FLOATER_MAX_SIZE;
- start_control_point.x = .5 * start_position.x;
- start_control_point.y = .5 * start_position.y;
- end_control_point.x = 1.5 * end_position.x;
- end_control_point.y = .5 * end_position.y;
-
- return path_new (&start_position, &start_control_point, &end_control_point,
- &end_position, duration);
-}
-
-static Path *
-screen_saver_floater_create_path_to_random_point (ScreenSaver *screen_saver,
- ScreenSaverFloater *floater,
- gdouble duration)
-{
- Point start_position, end_position, start_control_point, end_control_point;
-
- start_position = floater->position;
-
- end_position.x = start_position.x +
- (g_random_double_range (-.5, .5) * 4 * FLOATER_MAX_SIZE);
- end_position.y = start_position.y +
- (g_random_double_range (-.5, .5) * 4 * FLOATER_MAX_SIZE);
-
- start_control_point.x = start_position.x + .95 * (end_position.x - start_position.x);
- start_control_point.y = start_position.y + .95 * (end_position.y - start_position.y);
-
- end_control_point.x = start_position.x + 1.0 * (end_position.x - start_position.x);
- end_control_point.y = start_position.y + 1.0 * (end_position.y - start_position.y);
-
- return path_new (&start_position, &start_control_point, &end_control_point,
- &end_position, duration);
-}
-
-static Path *
-screen_saver_floater_create_path (ScreenSaver *screen_saver,
- ScreenSaverFloater *floater)
-{
- gdouble performance_ratio;
- gdouble duration;
-
- performance_ratio =
- screen_saver_get_frames_per_second (screen_saver) / OPTIMAL_FRAME_RATE;
-
- if (abs (performance_ratio) <= G_MINDOUBLE)
- performance_ratio = 1.0;
-
- if (screen_saver_floater_should_bubble_up (screen_saver, floater, performance_ratio, &duration))
- return screen_saver_floater_create_path_to_bubble_up (screen_saver, floater, duration);
-
- if (screen_saver_floater_should_come_on_screen (screen_saver, floater, performance_ratio, &duration))
- return screen_saver_floater_create_path_to_on_screen (screen_saver, floater, duration);
-
- return screen_saver_floater_create_path_to_random_point (screen_saver, floater,
- g_random_double_range (3.0, 7.0));
-}
-
-static void
-screen_saver_floater_update_state (ScreenSaver *screen_saver,
- ScreenSaverFloater *floater,
- gdouble time)
-{
- gdouble performance_ratio;
-
- performance_ratio =
- screen_saver_get_frames_per_second (screen_saver) / OPTIMAL_FRAME_RATE;
-
- if (floater->path == NULL)
- {
- floater->path = screen_saver_floater_create_path (screen_saver, floater);
- floater->path_start_time = time;
-
- floater->path_start_scale = floater->scale;
-
- if (g_random_double () > .5)
- floater->path_end_scale = g_random_double_range (0.10, performance_ratio);
-
- /* poor man's distribution */
- if (screen_saver->should_do_rotations &&
- (g_random_double () < .75 * performance_ratio))
- {
- gint r;
-
- r = g_random_int_range (0, 100);
- if (r < 80)
- floater->angle_increment = 0.0;
- else if (r < 95)
- floater->angle_increment = g_random_double_range (-SMALL_ANGLE, SMALL_ANGLE);
- else
- floater->angle_increment = g_random_double_range (-BIG_ANGLE, BIG_ANGLE);
- }
- }
-
- if (time < (floater->path_start_time + floater->path->duration))
- {
- gdouble path_time;
-
- path_time = time - floater->path_start_time;
-
- floater->position =
- screen_saver_floater_get_position_from_time (screen_saver, floater,
- path_time);
- floater->scale =
- screen_saver_floater_get_scale_from_time (screen_saver, floater, path_time);
-
- floater->angle =
- screen_saver_floater_get_angle_from_time (screen_saver, floater, path_time);
-
- floater->opacity = pow (floater->scale, 1.0 / GAMMA);
- }
- else
- {
- path_free (floater->path);
-
- floater->path = NULL;
- floater->path_start_time = 0.0;
- }
-}
-
-static GdkPixbuf *
-gamma_correct (const GdkPixbuf *input_pixbuf)
-{
- gint x, y, width, height, rowstride;
- GdkPixbuf *output_pixbuf;
- guchar *pixels;
-
- output_pixbuf = gdk_pixbuf_copy (input_pixbuf);
- pixels = gdk_pixbuf_get_pixels (output_pixbuf);
-
- width = gdk_pixbuf_get_width (output_pixbuf);
- height = gdk_pixbuf_get_height (output_pixbuf);
- rowstride = gdk_pixbuf_get_rowstride (output_pixbuf);
-
- for (y = 0; y < height; y++)
- for (x = 0; x < width; x++)
- {
- guchar *alpha_channel;
- guchar opacity;
-
- alpha_channel = pixels + y * (rowstride / 4) + x + 3;
- opacity = (guchar) (255 * pow ((*alpha_channel / 255.0), 1.0 / GAMMA));
-
- *alpha_channel = opacity;
- }
-
- return output_pixbuf;
-}
-
-static gboolean
-screen_saver_floater_do_draw (ScreenSaver *screen_saver,
- ScreenSaverFloater *floater,
- cairo_t *context)
-{
- gint size;
- CachedSource *source;
-
- size = CLAMP ((int) (FLOATER_MAX_SIZE * floater->scale),
- FLOATER_MIN_SIZE, FLOATER_MAX_SIZE);
-
- source = g_hash_table_lookup (screen_saver->cached_sources, GINT_TO_POINTER (size));
-
- if (source == NULL)
- {
- GdkPixbuf *pixbuf;
- GError *error;
-
- pixbuf = NULL;
- error = NULL;
-
- pixbuf = gdk_pixbuf_new_from_file_at_size (screen_saver->filename, size, -1,
- &error);
- if (pixbuf == NULL)
- {
- g_assert (error != NULL);
- g_printerr ("%s", _(error->message));
- g_error_free (error);
- return FALSE;
- }
-
- if (gdk_pixbuf_get_has_alpha (pixbuf))
- gamma_correct (pixbuf);
-
- gdk_cairo_set_source_pixbuf (context, pixbuf, 0.0, 0.0);
-
- source = cached_source_new (cairo_get_source (context),
- gdk_pixbuf_get_width (pixbuf),
- gdk_pixbuf_get_height (pixbuf));
- g_object_unref (pixbuf);
- g_hash_table_insert (screen_saver->cached_sources, GINT_TO_POINTER (size),
- source);
- }
-
- cairo_save (context);
-
- if (screen_saver->should_do_rotations && (abs (floater->angle) > G_MINDOUBLE))
- {
- floater->bounds.width = G_SQRT2 * source->width + 2;
- floater->bounds.height = G_SQRT2 * source->height + 2;
- floater->bounds.x = (int) (floater->position.x - .5 * G_SQRT2 * source->width) - 1;
- floater->bounds.y = (int) (floater->position.y - .5 * G_SQRT2 * source->height) - 1;
-
- cairo_translate (context,
- trunc (floater->position.x),
- trunc (floater->position.y));
- cairo_rotate (context, floater->angle);
- cairo_translate (context,
- -trunc (floater->position.x),
- -trunc (floater->position.y));
- }
- else
- {
- floater->bounds.width = source->width + 2;
- floater->bounds.height = source->height + 2;
- floater->bounds.x = (int) (floater->position.x - .5 * source->width) - 1;
- floater->bounds.y = (int) (floater->position.y - .5 * source->height) - 1;
- }
-
- cairo_translate (context,
- trunc (floater->position.x - .5 * source->width),
- trunc (floater->position.y - .5 * source->height));
-
- cairo_set_source (context, source->pattern);
-
- cairo_rectangle (context,
- trunc (.5 * (source->width - floater->bounds.width)),
- trunc (.5 * (source->height - floater->bounds.height)),
- floater->bounds.width, floater->bounds.height);
-
- cairo_clip (context);
- cairo_paint_with_alpha (context, floater->opacity);
- cairo_restore (context);
-
- if (screen_saver->should_show_paths && (floater->path != NULL))
- {
- gdouble dash_pattern[] = { 5.0 };
- gint size;
-
- size = CLAMP ((int) (FLOATER_MAX_SIZE * floater->path_start_scale),
- FLOATER_MIN_SIZE, FLOATER_MAX_SIZE);
-
- cairo_save (context);
- cairo_set_source_rgba (context, 1.0, 1.0, 1.0, .2 * floater->opacity);
- cairo_move_to (context,
- floater->path->start_point.x,
- floater->path->start_point.y);
- cairo_curve_to (context,
- floater->path->start_control_point.x,
- floater->path->start_control_point.y,
- floater->path->end_control_point.x,
- floater->path->end_control_point.y,
- floater->path->end_point.x,
- floater->path->end_point.y);
- cairo_set_line_cap (context, CAIRO_LINE_CAP_ROUND);
- cairo_stroke (context);
- cairo_set_source_rgba (context, 1.0, 0.0, 0.0, .5 * floater->opacity);
- cairo_rectangle (context,
- floater->path->start_point.x - 3,
- floater->path->start_point.y - 3,
- 6, 6);
- cairo_fill (context);
- cairo_set_source_rgba (context, 0.0, 0.5, 0.0, .5 * floater->opacity);
- cairo_arc (context,
- floater->path->start_control_point.x,
- floater->path->start_control_point.y,
- 3, 0.0, 2.0 * G_PI);
- cairo_stroke (context);
- cairo_set_source_rgba (context, 0.5, 0.0, 0.5, .5 * floater->opacity);
- cairo_arc (context,
- floater->path->end_control_point.x,
- floater->path->end_control_point.y,
- 3, 0.0, 2.0 * G_PI);
- cairo_stroke (context);
- cairo_set_source_rgba (context, 0.0, 0.0, 1.0, .5 * floater->opacity);
- cairo_rectangle (context,
- floater->path->end_point.x - 3,
- floater->path->end_point.y - 3,
- 6, 6);
- cairo_fill (context);
-
- cairo_set_dash (context, dash_pattern, G_N_ELEMENTS (dash_pattern), 0);
- cairo_set_source_rgba (context, .5, .5, .5, .2 * floater->scale);
- cairo_move_to (context, floater->path->start_point.x,
- floater->path->start_point.y);
- cairo_line_to (context, floater->path->start_control_point.x,
- floater->path->start_control_point.y);
- cairo_stroke (context);
-
- cairo_move_to (context, floater->path->end_point.x,
- floater->path->end_point.y);
- cairo_line_to (context, floater->path->end_control_point.x,
- floater->path->end_control_point.y);
- cairo_stroke (context);
-
- cairo_restore (context);
- }
-
- return TRUE;
-}
-
-static ScreenSaver *
-screen_saver_new (GtkDrawingArea *drawing_area,
- const gchar *filename,
- gint max_floater_count,
- gboolean should_do_rotations,
- gboolean should_show_paths)
-{
- ScreenSaver *screen_saver;
-
- screen_saver = g_new (ScreenSaver, 1);
- screen_saver->filename = g_strdup (filename);
- screen_saver->drawing_area = GTK_WIDGET (drawing_area);
- screen_saver->cached_sources =
- g_hash_table_new_full (NULL, NULL, NULL,
- (GDestroyNotify) cached_source_free);
-
- g_signal_connect_swapped (G_OBJECT (drawing_area), "size-allocate",
- G_CALLBACK (screen_saver_on_size_allocate),
- screen_saver);
-
- g_signal_connect_swapped (G_OBJECT (drawing_area), "expose-event",
- G_CALLBACK (screen_saver_on_expose_event),
- screen_saver);
-
- screen_saver->first_update_time = 0.0;
- screen_saver->current_calculated_stats_time = 0.0;
- screen_saver->last_calculated_stats_time = 0.0;
- screen_saver->update_count = 0;
- screen_saver->frame_count = 0;
- screen_saver->updates_per_second = 0.0;
- screen_saver->frames_per_second = 0.0;
- screen_saver->floaters = NULL;
- screen_saver->max_floater_count = max_floater_count;
-
- screen_saver->should_show_paths = should_show_paths;
- screen_saver->should_do_rotations = should_do_rotations;
-
- screen_saver_get_initial_state (screen_saver);
-
- screen_saver->state_update_timeout_id =
- g_timeout_add (1000 / (2.0 * OPTIMAL_FRAME_RATE),
- (GSourceFunc) screen_saver_do_update_state, screen_saver);
-
- screen_saver->stats_update_timeout_id =
- g_timeout_add (1000, (GSourceFunc) screen_saver_do_update_stats,
- screen_saver);
-
- return screen_saver;
-}
-
-static void
-screen_saver_free (ScreenSaver *screen_saver)
-{
- if (screen_saver == NULL)
- return;
-
- g_free (screen_saver->filename);
-
- g_hash_table_destroy (screen_saver->cached_sources);
-
- if (screen_saver->state_update_timeout_id != 0)
- g_source_remove (screen_saver->state_update_timeout_id);
-
- if (screen_saver->stats_update_timeout_id != 0)
- g_source_remove (screen_saver->stats_update_timeout_id);
-
- screen_saver_destroy_floaters (screen_saver);
-
- g_free (screen_saver);
-}
-
-static gdouble
-screen_saver_get_timestamp (ScreenSaver *screen_saver)
-{
- const gdouble microseconds_per_second = (gdouble ) G_USEC_PER_SEC;
- gdouble timestamp;
- GTimeVal now = { 0L, /* zero-filled */ };
-
- g_get_current_time (&now);
- timestamp = ((microseconds_per_second * now.tv_sec) + now.tv_usec) /
- microseconds_per_second;
-
- return timestamp;
-}
-
-static void
-screen_saver_create_floaters (ScreenSaver *screen_saver)
-{
- gint i;
-
- for (i = 0; i < screen_saver->max_floater_count; i++)
- {
- ScreenSaverFloater *floater;
- Point position;
- gdouble scale;
-
- position.x = g_random_double_range (screen_saver->canvas_rectangle.top_left_point.x,
- screen_saver->canvas_rectangle.bottom_right_point.x);
- position.y = g_random_double_range (screen_saver->canvas_rectangle.top_left_point.y,
- screen_saver->canvas_rectangle.bottom_right_point.y);
-
- scale = g_random_double ();
-
- floater = screen_saver_floater_new (screen_saver, &position, scale);
-
- screen_saver->floaters = g_list_prepend (screen_saver->floaters,
- floater);
- }
-}
-
-static gdouble
-screen_saver_get_updates_per_second (ScreenSaver *screen_saver)
-{
- return screen_saver->updates_per_second;
-}
-
-static gdouble
-screen_saver_get_frames_per_second (ScreenSaver *screen_saver)
-{
- return screen_saver->frames_per_second;
-}
-
-static gdouble
-screen_saver_get_image_cache_usage (ScreenSaver *screen_saver)
-{
- static const gdouble cache_capacity = (FLOATER_MAX_SIZE - FLOATER_MIN_SIZE + 1);
-
- return g_hash_table_size (screen_saver->cached_sources) / cache_capacity;
-}
-
-static void
-screen_saver_destroy_floaters (ScreenSaver *screen_saver)
-{
- if (screen_saver->floaters == NULL)
- return;
-
- g_list_foreach (screen_saver->floaters, (GFunc) screen_saver_floater_free,
- NULL);
- g_list_free (screen_saver->floaters);
-
- screen_saver->floaters = NULL;
-}
-
-static void
-screen_saver_on_size_allocate (ScreenSaver *screen_saver,
- GtkAllocation *allocation)
-{
- Rectangle canvas_rectangle;
-
- canvas_rectangle.top_left_point.x = allocation->x - .1 * allocation->width;
- canvas_rectangle.top_left_point.y = allocation->y - .1 * allocation->height;
-
- canvas_rectangle.bottom_right_point.x = allocation->x + (1.1 * allocation->width);
- canvas_rectangle.bottom_right_point.y = allocation->y + (1.1 * allocation->height);
-
- screen_saver->canvas_rectangle = canvas_rectangle;
-}
-
-static gint
-compare_floaters (ScreenSaverFloater *a,
- ScreenSaverFloater *b)
-{
- if (a->scale > b->scale)
- return 1;
- else if (abs (a->scale - b->scale) <= G_MINDOUBLE)
- return 0;
- else
- return -1;
-}
-
-static void
-screen_saver_on_expose_event (ScreenSaver *screen_saver,
- GdkEventExpose *event)
-{
- GList *tmp;
- cairo_t *context;
-
- if (screen_saver->floaters == NULL)
- screen_saver_create_floaters (screen_saver);
-
- context = gdk_cairo_create (screen_saver->drawing_area->window);
-
- cairo_rectangle (context,
- (double) event->area.x,
- (double) event->area.y,
- (double) event->area.width,
- (double) event->area.height);
- cairo_clip (context);
-
- screen_saver->floaters = g_list_sort (screen_saver->floaters,
- (GCompareFunc)compare_floaters);
-
- for (tmp = screen_saver->floaters; tmp != NULL; tmp = tmp->next)
- {
- ScreenSaverFloater *floater;
- GdkRectangle rect;
- gint size;
-
- floater = (ScreenSaverFloater *) tmp->data;
-
- size = CLAMP ((int) (FLOATER_MAX_SIZE * floater->scale),
- FLOATER_MIN_SIZE, FLOATER_MAX_SIZE);
-
- rect.x = (int) (floater->position.x - .5 * G_SQRT2 * size);
- rect.y = (int) (floater->position.y - .5 * G_SQRT2 * size);
- rect.width = G_SQRT2 * size;
- rect.height = G_SQRT2 * size;
-
- if (!gdk_region_rect_in (event->region, &rect))
- continue;
-
- if (!screen_saver_floater_do_draw (screen_saver, floater, context))
- {
- gtk_main_quit ();
- break;
- }
- }
-
- cairo_destroy (context);
-
- screen_saver->draw_ops_pending = TRUE;
- screen_saver->frame_count++;
-}
-
-static void
-screen_saver_update_state (ScreenSaver *screen_saver,
- gdouble time)
-{
- GList *tmp;
-
- tmp = screen_saver->floaters;
- while (tmp != NULL)
- {
- ScreenSaverFloater *floater;
- floater = (ScreenSaverFloater *) tmp->data;
-
- screen_saver_floater_update_state (screen_saver, floater, time);
-
- if (GTK_WIDGET_REALIZED (screen_saver->drawing_area)
- && (floater->bounds.width > 0) && (floater->bounds.height > 0))
- {
- gint size;
- size = CLAMP ((int) (FLOATER_MAX_SIZE * floater->scale),
- FLOATER_MIN_SIZE, FLOATER_MAX_SIZE);
-
- gtk_widget_queue_draw_area (screen_saver->drawing_area,
- floater->bounds.x,
- floater->bounds.y,
- floater->bounds.width,
- floater->bounds.height);
-
- /* the edges could concievably be spread across two
- * pixels so we add +2 to invalidated region
- */
- if (screen_saver->should_do_rotations)
- gtk_widget_queue_draw_area (screen_saver->drawing_area,
- (int) (floater->position.x -
- .5 * G_SQRT2 * size),
- (int) (floater->position.y -
- .5 * G_SQRT2 * size),
- G_SQRT2 * size + 2,
- G_SQRT2 * size + 2);
- else
- gtk_widget_queue_draw_area (screen_saver->drawing_area,
- (int) (floater->position.x -
- .5 * size),
- (int) (floater->position.y -
- .5 * size),
- size + 2, size + 2);
-
- if (screen_saver->should_show_paths)
- gtk_widget_queue_draw (screen_saver->drawing_area);
- }
-
- tmp = tmp->next;
- }
-}
-
-static void
-screen_saver_get_initial_state (ScreenSaver *screen_saver)
-{
- screen_saver->first_update_time = screen_saver_get_timestamp (screen_saver);
- screen_saver_update_state (screen_saver, 0.0);
-}
-
-static gboolean
-screen_saver_do_update_state (ScreenSaver *screen_saver)
-{
- gdouble current_update_time;
-
- /* flush pending requests to the X server and block for
- * replies before proceeding to help prevent the X server from
- * getting overrun with requests
- */
- if (screen_saver->draw_ops_pending)
- {
- gdk_flush ();
- screen_saver->draw_ops_pending = FALSE;
- }
-
- current_update_time = screen_saver_get_timestamp (screen_saver);
- screen_saver_update_state (screen_saver, current_update_time -
- screen_saver->first_update_time);
- screen_saver->update_count++;
- return TRUE;
-}
-
-static gboolean
-screen_saver_do_update_stats (ScreenSaver *screen_saver)
-{
- gdouble last_calculated_stats_time, seconds_since_last_stats_update;
-
- last_calculated_stats_time = screen_saver->current_calculated_stats_time;
- screen_saver->current_calculated_stats_time =
- screen_saver_get_timestamp (screen_saver);
- screen_saver->last_calculated_stats_time = last_calculated_stats_time;
-
- if (abs (last_calculated_stats_time) <= G_MINDOUBLE)
- return TRUE;
-
- seconds_since_last_stats_update =
- screen_saver->current_calculated_stats_time - last_calculated_stats_time;
-
- screen_saver->updates_per_second =
- screen_saver->update_count / seconds_since_last_stats_update;
- screen_saver->frames_per_second =
- screen_saver->frame_count / seconds_since_last_stats_update;
-
- screen_saver->update_count = 0;
- screen_saver->frame_count = 0;
-
- return TRUE;
-}
-
-static gboolean
-do_print_screen_saver_stats (ScreenSaver *screen_saver)
-{
-
- g_print ("updates per second: %.2f, frames per second: %.2f, "
- "image cache %.0f%% full\n",
- screen_saver_get_updates_per_second (screen_saver),
- screen_saver_get_frames_per_second (screen_saver),
- screen_saver_get_image_cache_usage (screen_saver) * 100.0);
-
- return TRUE;
-}
-
-int
-main (int argc,
- char *argv[])
-{
- ScreenSaver *screen_saver;
- GtkWidget *window;
- GtkWidget *drawing_area;
-
- GtkStateType state;
-
- GError *error;
-
- error = NULL;
-
- bindtextdomain (GETTEXT_PACKAGE, MATELOCALEDIR);
- bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8");
- textdomain (GETTEXT_PACKAGE);
-
- gtk_init_with_args (&argc, &argv,
- /* translators: the word "image" here
- * represents a command line argument
- */
- _("image - floats images around the screen"),
- options, GETTEXT_PACKAGE, &error);
-
-
- if (error != NULL)
- {
- g_printerr (_("%s. See --help for usage information.\n"),
- _(error->message));
- g_error_free (error);
- return EX_SOFTWARE;
- }
-
- if ((filenames == NULL) || (filenames[0] == NULL) ||
- (filenames[1] != NULL))
- {
- g_printerr (_("You must specify one image. See --help for usage "
- "information.\n"));
- return EX_USAGE;
- }
-
- window = gs_theme_window_new ();
-
- g_signal_connect (G_OBJECT (window), "delete-event",
- G_CALLBACK (gtk_main_quit), NULL);
-
- drawing_area = gtk_drawing_area_new ();
-
- state = (GtkStateType) 0;
- while (state < (GtkStateType) G_N_ELEMENTS (drawing_area->style->bg))
- {
- gtk_widget_modify_bg (drawing_area, state, &drawing_area->style->mid[state]);
- state++;
- }
-
- gtk_widget_show (drawing_area);
- gtk_container_add (GTK_CONTAINER (window), drawing_area);
-
- screen_saver = screen_saver_new (GTK_DRAWING_AREA (drawing_area),
- filenames[0], max_floater_count,
- should_do_rotations, should_show_paths);
- g_strfreev (filenames);
-
- if (should_print_stats)
- g_timeout_add (STAT_PRINT_FREQUENCY,
- (GSourceFunc) do_print_screen_saver_stats,
- screen_saver);
-
- if ((geometry == NULL)
- || !gtk_window_parse_geometry (GTK_WINDOW (window), geometry))
- gtk_window_set_default_size (GTK_WINDOW (window), 640, 480);
-
- gtk_widget_show (window);
-
- gtk_main ();
-
- screen_saver_free (screen_saver);
-
- return EX_OK;
-}