/* * Copyright © 2004 David Reveman, Peter Nilsson * * Permission to use, copy, modify, distribute, and sell this software * and its documentation for any purpose is hereby granted without * fee, provided that the above copyright notice appear in all copies * and that both that copyright notice and this permission notice * appear in supporting documentation, and that the names of * David Reveman and Peter Nilsson not be used in advertising or * publicity pertaining to distribution of the software without * specific, written prior permission. David Reveman and Peter Nilsson * makes no representations about the suitability of this software for * any purpose. It is provided "as is" without express or implied warranty. * * DAVID REVEMAN AND PETER NILSSON DISCLAIMS ALL WARRANTIES WITH * REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL DAVID REVEMAN AND * PETER NILSSON BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA * OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR * PERFORMANCE OF THIS SOFTWARE. * * Authors: David Reveman * Peter Nilsson */ #include #include #include #include #include "fdface.h" #include "fdhand.h" #define PRECISION int /* int/float */ #define TRUNC(x) ((PRECISION) (x)) static cairo_surface_t *clock_bg_surface; static cairo_surface_t *clock_surface; static cairo_surface_t *glider_surface; static cairo_surface_t *fakewin_surface; static cairo_surface_t *bg_surface; static int bg_width, bg_height; #define CLOCK_W 256 #define CLOCK_H 245 static int fakewin_width; static int fakewin_height; static int glider_width; static int glider_height; static double glider_angle = 0; static double glider_pos_x = 80; static double glider_pos_y = 50; static double glider_dir_x = 1; static double glider_dir_y = 1; static void render_fakewin (void) { cairo_t *cr; cr = cairo_create (fakewin_surface); cairo_set_operator (cr, CAIRO_OPERATOR_SOURCE); cairo_set_source_rgb (cr, 1.0, 1.0, 1.0); cairo_move_to (cr, 0, 0); cairo_rectangle (cr, 17, 34, fakewin_width - 32, fakewin_height - 50); cairo_fill (cr); cairo_set_operator (cr, CAIRO_OPERATOR_OVER); cairo_translate (cr, TRUNC (glider_pos_x), TRUNC (glider_pos_y)); cairo_set_source_surface (cr, glider_surface, 0.0, 0.0); cairo_paint (cr); cairo_destroy (cr); glider_pos_x += glider_dir_x; glider_pos_y += glider_dir_y; if (glider_pos_x <= 18) glider_dir_x = -glider_dir_x; if (glider_pos_y <= 35) glider_dir_y = -glider_dir_y; if (glider_pos_x >= (fakewin_width - 16 - 37)) glider_dir_x = -glider_dir_x; if (glider_pos_y >= (fakewin_height - 19 - 37)) glider_dir_y = -glider_dir_y; } static void render_clock (void) { cairo_t *cr; cr = cairo_create (clock_surface); cairo_set_operator (cr, CAIRO_OPERATOR_CLEAR); cairo_paint (cr); cairo_set_operator (cr, CAIRO_OPERATOR_OVER); cairo_set_source_surface (cr, clock_bg_surface, 0.0, 0.0); cairo_paint (cr); fdhand_draw_now (cr, CLOCK_W, CLOCK_H, 1); cairo_destroy (cr); } void shadow_setup (cairo_surface_t *target, int w, int h) { cairo_surface_t *image; cairo_t *cr; clock_surface = cairo_surface_create_similar (target, CAIRO_CONTENT_COLOR_ALPHA, CLOCK_W, CLOCK_H); clock_bg_surface = cairo_surface_create_similar (target, CAIRO_CONTENT_COLOR_ALPHA, CLOCK_W, CLOCK_H); image = cairo_image_surface_create_from_png ("desktop.png"); if (cairo_surface_status (image)) { printf ("error reading desktop.png: %s\n", cairo_status_to_string (cairo_surface_status (image))); exit(1); } bg_width = cairo_image_surface_get_width (image); bg_height = cairo_image_surface_get_height (image); bg_surface = cairo_surface_create_similar (target, cairo_surface_get_content (image), bg_width, bg_height); cr = cairo_create (bg_surface); cairo_set_operator (cr, CAIRO_OPERATOR_SOURCE); cairo_set_source_surface (cr, image, 0.0, 0.0); cairo_paint (cr); cairo_destroy (cr); cairo_surface_destroy (image); image = cairo_image_surface_create_from_png ("fakewin.png"); if (cairo_surface_status (image)) { printf ("error reading fakewin.png: %s\n", cairo_status_to_string (cairo_surface_status (image))); exit(1); } fakewin_width = cairo_image_surface_get_width (image); fakewin_height = cairo_image_surface_get_height (image); fakewin_surface = cairo_surface_create_similar (target, cairo_surface_get_content (image), fakewin_width + 2, fakewin_height + 2); cr = cairo_create (fakewin_surface); cairo_set_operator (cr, CAIRO_OPERATOR_SOURCE); cairo_set_source_surface (cr, image, 0.0, 0.0); cairo_paint (cr); cairo_destroy (cr); image = cairo_image_surface_create_from_png ("glider.png"); if (cairo_surface_status (image)) { printf ("error reading glider.png: %s\n", cairo_status_to_string (cairo_surface_status (image))); exit(1); } glider_width = cairo_image_surface_get_width (image); glider_height = cairo_image_surface_get_height (image); glider_surface = cairo_surface_create_similar (target, cairo_surface_get_content (image), glider_width, glider_height); cr = cairo_create (glider_surface); cairo_set_operator (cr, CAIRO_OPERATOR_SOURCE); cairo_set_source_surface (cr, image, 0.0, 0.0); cairo_paint (cr); cairo_destroy (cr); cr = cairo_create (clock_bg_surface); cairo_set_operator (cr, CAIRO_OPERATOR_SOURCE); cairo_set_source_rgba(cr, 1.0, 1.0, 1.0, 0.0); cairo_rectangle (cr, 0, 0, CLOCK_W, CLOCK_H); cairo_fill (cr); cairo_save (cr); cairo_set_source_rgba (cr, 1.0, 1.0, 1.0, 0.25); cairo_set_operator (cr, CAIRO_OPERATOR_OVER); cairo_scale (cr, CLOCK_W, CLOCK_H); cairo_translate (cr, 0.5, 0.5); cairo_arc (cr, 0, 0, 0.5, 0, 2 * M_PI); cairo_fill (cr); cairo_restore (cr); cairo_set_source_rgb (cr, 1.0, 1.0, 1.0); cairo_set_operator (cr, CAIRO_OPERATOR_OVER); fdface_draw (cr, CLOCK_W, CLOCK_H); cairo_destroy (cr); cairo_surface_destroy (image); render_clock (); render_fakewin (); } static long int shadow_cnt = 0; static double fw_x = 250.0, fw_y = 20.0; static double cl_x = 50.0, cl_y = 180.0; static double dst_x = 20.0, dst_y = 270.0; static double start_x = 250.0, start_y = 20.0; static int which = 1; static int shadow_move_towards_point (double *current_x, double *current_y) { double to_go_x = dst_x - *current_x; double to_go_y = dst_y - *current_y; double done_x = *current_x - start_x; double done_y = *current_y - start_y; double dist_from_start = fabs (to_go_x) + fabs (to_go_y); double dist_from_goal = fabs (done_x) + fabs (done_y); double speed = (dist_from_start < dist_from_goal) ? dist_from_start: dist_from_goal; double speed_div; double angle; speed *= 10.0; speed_div = fabs (dst_x - start_x) + fabs (dst_y - start_y); speed /= (speed_div > 1.0)? speed_div: 1.0; speed += 0.1; angle = fabs (atan (to_go_y / to_go_x)); *current_x += speed * cos (angle) * ((dst_x > start_x)? 1.0: -1.0); *current_y += speed * sin (angle) * ((dst_y > start_y)? 1.0: -1.0); if (start_x <= dst_x) { if (*current_x >= dst_x) return 1; } else { if (*current_x <= dst_x) return 1; } if (start_y <= dst_y) { if (*current_y >= dst_y) return 1; } else { if (*current_y <= dst_y) return 1; } return 0; } static double shadow_alpha = 0.4; static double max_shadow_offset = 60.0; void shadow_render (cairo_t *cr, int w, int h) { double scale_x, scale_y; int move_done; double shadow_offset_x, shadow_offset_y; double light_x, light_y; light_x = w / 2.0; light_y = h / 2.0; cairo_save (cr); cairo_save (cr); cairo_set_operator (cr, CAIRO_OPERATOR_SOURCE); scale_x = ((double) w) / (double) bg_width; scale_y = ((double) h) / (double) bg_height; cairo_scale (cr, scale_x, scale_y); cairo_set_source_surface (cr, bg_surface, 0.0, 0.0); cairo_paint (cr); cairo_restore (cr); cairo_set_operator (cr, CAIRO_OPERATOR_OVER); if (!(shadow_cnt % 10)) render_clock (); else if (!(shadow_cnt % 5)) render_fakewin (); shadow_cnt++; if (shadow_cnt >= 1000000) shadow_cnt = 0; shadow_offset_x = max_shadow_offset * ((fw_x + fakewin_width / 2) - light_x) / (w / 2.0); shadow_offset_y = max_shadow_offset * ((fw_y + fakewin_height / 2) - light_y) / (h / 2.0); /* hard shadow */ cairo_set_source_rgba (cr, 0.0, 0.0, 0.0, shadow_alpha); cairo_mask_surface (cr, fakewin_surface, TRUNC (fw_x + shadow_offset_x - 0.05 * fakewin_width), TRUNC (fw_y + shadow_offset_y - 0.05 * fakewin_height)); cairo_paint (cr); cairo_set_source_surface (cr, fakewin_surface, TRUNC (fw_x), TRUNC (fw_y)); cairo_paint (cr); shadow_offset_x = max_shadow_offset * ((cl_x + CLOCK_W / 2) - light_x) / (w / 2.0); shadow_offset_y = max_shadow_offset * ((cl_y + CLOCK_H / 2) - light_y) / (h / 2.0); /* soft (translucent) shadow */ cairo_set_source_surface (cr, clock_surface, TRUNC (cl_x + shadow_offset_x - 0.05 * CLOCK_W), TRUNC (cl_y + shadow_offset_y - 0.05 * CLOCK_H)); cairo_paint_with_alpha (cr, shadow_alpha); cairo_set_source_surface (cr, clock_surface, TRUNC (cl_x), TRUNC (cl_y)); cairo_paint (cr); if (which) { move_done = shadow_move_towards_point (&fw_x, &fw_y); } else { move_done = shadow_move_towards_point (&cl_x, &cl_y); } if (move_done) { which = (int) (drand48 () + 0.5); dst_x = drand48 () * (w - ((which)? fakewin_width : CLOCK_W) - max_shadow_offset); dst_y = drand48 () * (h - ((which)? fakewin_height: CLOCK_H) - max_shadow_offset); if (which) { start_x = fw_x; start_y = fw_y; } else { start_x = cl_x; start_y = cl_y; } } cairo_restore (cr); }