From 8fa6fec9d86dbe34be626652cda0fba4f4803223 Mon Sep 17 00:00:00 2001 From: Ray Strode Date: Tue, 22 Oct 2013 18:34:46 -0400 Subject: [PATCH 1/5] pixel-buffer: add tiling function It can be useful to tile a group of pixels across the screen (for e.g. backgrounds). This commit adds API to pixel buffer to do that tiling. A follow up commit will add support into ply-image so images can be loaded from disk and then tiled on screen. --- src/libply-splash-core/ply-pixel-buffer.c | 30 ++++++++++++++++++++++++++++++ src/libply-splash-core/ply-pixel-buffer.h | 4 ++++ 2 files changed, 34 insertions(+) diff --git a/src/libply-splash-core/ply-pixel-buffer.c b/src/libply-splash-core/ply-pixel-buffer.c index a612990..a860b7f 100644 --- a/src/libply-splash-core/ply-pixel-buffer.c +++ b/src/libply-splash-core/ply-pixel-buffer.c @@ -821,32 +821,62 @@ ply_pixel_buffer_rotate (ply_pixel_buffer_t *old_buffer, bytes = ply_pixel_buffer_get_argb32_data (buffer); double d = sqrt ((center_x * center_x + center_y * center_y)); double theta = atan2 (-center_y, -center_x) - theta_offset; double start_x = center_x + d * cos (theta); double start_y = center_y + d * sin (theta); double step_x = cos (-theta_offset); double step_y = sin (-theta_offset); for (y = 0; y < height; y++) { old_y = start_y; old_x = start_x; start_y += step_x; start_x -= step_y; for (x = 0; x < width; x++) { if (old_x < 0 || old_x > width || old_y < 0 || old_y > height) bytes[x + y * width] = 0; else bytes[x + y * width] = ply_pixel_buffer_interpolate (old_buffer, old_x, old_y); old_x += step_x; old_y += step_y; } } return buffer; } +ply_pixel_buffer_t * +ply_pixel_buffer_tile (ply_pixel_buffer_t *old_buffer, + long width, + long height) +{ + long x, y; + long old_x, old_y; + long old_width, old_height; + uint32_t *bytes, *old_bytes; + ply_pixel_buffer_t *buffer; + + buffer = ply_pixel_buffer_new (width, height); + + old_bytes = ply_pixel_buffer_get_argb32_data (old_buffer); + bytes = ply_pixel_buffer_get_argb32_data (buffer); + + old_width = old_buffer->area.width; + old_height = old_buffer->area.height; + + for (y = 0; y < height; y++) + { + old_y = y % old_height; + for (x = 0; x < width; x++) + { + old_x = x % old_width; + bytes[x + y * width] = old_bytes[old_x + old_y * old_width]; + } + } + return buffer; +} /* vim: set ts=4 sw=4 et ai ci cino={.5s,^-2,+.5s,t0,g0,e-2,n-2,p2s,(0,=.5s,:.5s */ diff --git a/src/libply-splash-core/ply-pixel-buffer.h b/src/libply-splash-core/ply-pixel-buffer.h index 47cdd52..e0dffda 100644 --- a/src/libply-splash-core/ply-pixel-buffer.h +++ b/src/libply-splash-core/ply-pixel-buffer.h @@ -97,34 +97,38 @@ void ply_pixel_buffer_fill_with_buffer_at_opacity (ply_pixel_buffer_t *canvas, ply_pixel_buffer_t *source, int x_offset, int y_offset, float opacity); void ply_pixel_buffer_fill_with_buffer_with_clip (ply_pixel_buffer_t *canvas, ply_pixel_buffer_t *source, int x_offset, int y_offset, ply_rectangle_t *clip_area); void ply_pixel_buffer_fill_with_buffer (ply_pixel_buffer_t *canvas, ply_pixel_buffer_t *source, int x_offset, int y_offset); void ply_pixel_buffer_push_clip_area (ply_pixel_buffer_t *buffer, ply_rectangle_t *clip_area); void ply_pixel_buffer_pop_clip_area (ply_pixel_buffer_t *buffer); uint32_t *ply_pixel_buffer_get_argb32_data (ply_pixel_buffer_t *buffer); ply_pixel_buffer_t *ply_pixel_buffer_resize (ply_pixel_buffer_t *old_buffer, long width, long height); ply_pixel_buffer_t *ply_pixel_buffer_rotate (ply_pixel_buffer_t *old_buffer, long center_x, long center_y, double theta_offset); +ply_pixel_buffer_t *ply_pixel_buffer_tile (ply_pixel_buffer_t *old_buffer, + long width, + long height); + #endif #endif /* PLY_PIXEL_BUFFER_H */ /* vim: set ts=4 sw=4 expandtab autoindent cindent cino={.5s,(0: */ -- 1.8.3.1 From fc440513d337ca15067039383502f73a0fe2796f Mon Sep 17 00:00:00 2001 From: Ray Strode Date: Tue, 22 Oct 2013 18:36:15 -0400 Subject: [PATCH 2/5] ply-image: add tiling support This follow up commit adds tiling support to images, so that splash screens can have been background patterns instead of just background colors. --- src/libply-splash-graphics/ply-image.c | 15 +++++++++++++++ src/libply-splash-graphics/ply-image.h | 1 + 2 files changed, 16 insertions(+) diff --git a/src/libply-splash-graphics/ply-image.c b/src/libply-splash-graphics/ply-image.c index be85809..7d21946 100644 --- a/src/libply-splash-graphics/ply-image.c +++ b/src/libply-splash-graphics/ply-image.c @@ -227,53 +227,68 @@ ply_image_resize (ply_image_t *image, long width, long height) { ply_image_t *new_image; new_image = ply_image_new (image->filename); new_image->buffer = ply_pixel_buffer_resize (image->buffer, width, height); return new_image; } ply_image_t * ply_image_rotate (ply_image_t *image, long center_x, long center_y, double theta_offset) { ply_image_t *new_image; new_image = ply_image_new (image->filename); new_image->buffer = ply_pixel_buffer_rotate (image->buffer, center_x, center_y, theta_offset); return new_image; } +ply_image_t * +ply_image_tile (ply_image_t *image, + long width, + long height) +{ + ply_image_t *new_image; + + new_image = ply_image_new (image->filename); + + new_image->buffer = ply_pixel_buffer_tile (image->buffer, + width, + height); + return new_image; +} + ply_pixel_buffer_t * ply_image_get_buffer (ply_image_t *image) { assert (image != NULL); return image->buffer; } ply_pixel_buffer_t * ply_image_convert_to_pixel_buffer (ply_image_t *image) { ply_pixel_buffer_t *buffer; assert (image != NULL); buffer = image->buffer; image->buffer = NULL; ply_image_free (image); return buffer; } /* vim: set ts=4 sw=4 expandtab autoindent cindent cino={.5s,(0: */ diff --git a/src/libply-splash-graphics/ply-image.h b/src/libply-splash-graphics/ply-image.h index 66fa520..5bda567 100644 --- a/src/libply-splash-graphics/ply-image.h +++ b/src/libply-splash-graphics/ply-image.h @@ -12,37 +12,38 @@ * 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., 59 Temple Place - Suite 330, Boston, MA * 02111-1307, USA. * * Written By: Ray Strode */ #ifndef PLY_IMAGE_H #define PLY_IMAGE_H #include "ply-pixel-buffer.h" #include #include #include typedef struct _ply_image ply_image_t; #ifndef PLY_HIDE_FUNCTION_DECLARATIONS ply_image_t *ply_image_new (const char *filename); void ply_image_free (ply_image_t *image); bool ply_image_load (ply_image_t *image); uint32_t *ply_image_get_data (ply_image_t *image); long ply_image_get_width (ply_image_t *image); long ply_image_get_height (ply_image_t *image); ply_image_t *ply_image_resize (ply_image_t *image, long width, long height); ply_image_t *ply_image_rotate (ply_image_t *oldimage, long center_x, long center_y, double theta_offset); +ply_image_t *ply_image_tile (ply_image_t *image, long width, long height); ply_pixel_buffer_t *ply_image_get_buffer (ply_image_t *image); ply_pixel_buffer_t *ply_image_convert_to_pixel_buffer (ply_image_t *image); #endif #endif /* PLY_IMAGE_H */ /* vim: set ts=4 sw=4 expandtab autoindent cindent cino={.5s,(0: */ -- 1.8.3.1 From 257408d44d1b5d0dc202f60f79d3d8f5c3427413 Mon Sep 17 00:00:00 2001 From: Ray Strode Date: Tue, 22 Oct 2013 19:24:14 -0400 Subject: [PATCH 3/5] two-step: add support for tiled background image If there's a file named background-tile.png in the theme then it will get used as the background behind the other content in place of the background gradient. --- src/plugins/splash/two-step/plugin.c | 45 ++++++++++++++++++++++++++++++++++++ 1 file changed, 45 insertions(+) diff --git a/src/plugins/splash/two-step/plugin.c b/src/plugins/splash/two-step/plugin.c index 541a108..2c6d97a 100644 --- a/src/plugins/splash/two-step/plugin.c +++ b/src/plugins/splash/two-step/plugin.c @@ -64,70 +64,72 @@ #define FRAMES_PER_SECOND 30 #endif #ifndef SHOW_ANIMATION_PERCENT #define SHOW_ANIMATION_PERCENT 0.9 #endif typedef enum { PLY_BOOT_SPLASH_DISPLAY_NORMAL, PLY_BOOT_SPLASH_DISPLAY_QUESTION_ENTRY, PLY_BOOT_SPLASH_DISPLAY_PASSWORD_ENTRY } ply_boot_splash_display_type_t; typedef enum { PROGRESS_FUNCTION_TYPE_WWOODS, PROGRESS_FUNCTION_TYPE_LINEAR, } progress_function_t; typedef struct { ply_boot_splash_plugin_t *plugin; ply_pixel_display_t *display; ply_entry_t *entry; ply_animation_t *end_animation; ply_progress_animation_t *progress_animation; ply_throbber_t *throbber; ply_label_t *label; ply_label_t *message_label; ply_rectangle_t box_area, lock_area; ply_trigger_t *end_trigger; + ply_image_t *background_image; } view_t; struct _ply_boot_splash_plugin { ply_event_loop_t *loop; ply_boot_splash_mode_t mode; ply_image_t *lock_image; ply_image_t *box_image; ply_image_t *corner_image; ply_image_t *header_image; + ply_image_t *background_tile_image; ply_list_t *views; ply_boot_splash_display_type_t state; double animation_horizontal_alignment; double animation_vertical_alignment; char *animation_dir; ply_progress_animation_transition_t transition; double transition_duration; uint32_t background_start_color; uint32_t background_end_color; progress_function_t progress_function; ply_trigger_t *idle_trigger; ply_trigger_t *stop_trigger; uint32_t root_is_mounted : 1; uint32_t is_visible : 1; uint32_t is_animating : 1; uint32_t is_idle : 1; }; ply_boot_splash_plugin_interface_t * ply_boot_splash_plugin_get_interface (void); static void stop_animation (ply_boot_splash_plugin_t *plugin, ply_trigger_t *idle_trigger); @@ -149,66 +151,83 @@ view_new (ply_boot_splash_plugin_t *plugin, view->entry = ply_entry_new (plugin->animation_dir); view->end_animation = ply_animation_new (plugin->animation_dir, "animation-"); view->progress_animation = ply_progress_animation_new (plugin->animation_dir, "progress-"); view->throbber = ply_throbber_new (plugin->animation_dir, "throbber-"); ply_progress_animation_set_transition (view->progress_animation, plugin->transition, plugin->transition_duration); view->label = ply_label_new (); view->message_label = ply_label_new (); return view; } static void view_free (view_t *view) { ply_entry_free (view->entry); ply_animation_free (view->end_animation); ply_progress_animation_free (view->progress_animation); ply_throbber_free (view->throbber); ply_label_free (view->label); ply_label_free (view->message_label); + if (view->background_image != NULL) + ply_image_free (view->background_image); + free (view); } static bool view_load (view_t *view) { + unsigned long screen_width, screen_height; + ply_boot_splash_plugin_t *plugin; + + plugin = view->plugin; + + screen_width = ply_pixel_display_get_width (view->display); + screen_height = ply_pixel_display_get_height (view->display); + + if (plugin->background_tile_image != NULL) + { + ply_trace ("tiling background to %lux%lu", screen_width, screen_height); + view->background_image = ply_image_tile (plugin->background_tile_image, screen_width, screen_height); + } + ply_trace ("loading entry"); if (!ply_entry_load (view->entry)) return false; ply_trace ("loading animation"); if (!ply_animation_load (view->end_animation)) { ply_trace ("Default animation wouldn't load, " "falling back to old naming scheme"); /* fallback to throbber- for compatibility */ ply_animation_free (view->end_animation); view->end_animation = ply_animation_new (view->plugin->animation_dir, "throbber-"); if (!ply_animation_load (view->end_animation)) { ply_trace ("old naming scheme didn't work either"); return false; } ply_throbber_free (view->throbber); view->throbber = NULL; } ply_trace ("loading progress animation"); if (!ply_progress_animation_load (view->progress_animation)) { ply_trace ("optional progress animation wouldn't load"); ply_progress_animation_free (view->progress_animation); @@ -492,60 +511,66 @@ create_plugin (ply_key_file_t *key_file) char *image_dir, *image_path; char *alignment; char *transition; char *transition_duration; char *color; char *progress_function; srand ((int) ply_get_timestamp ()); plugin = calloc (1, sizeof (ply_boot_splash_plugin_t)); image_dir = ply_key_file_get_value (key_file, "two-step", "ImageDir"); ply_trace ("Using '%s' as working directory", image_dir); asprintf (&image_path, "%s/lock.png", image_dir); plugin->lock_image = ply_image_new (image_path); free (image_path); asprintf (&image_path, "%s/box.png", image_dir); plugin->box_image = ply_image_new (image_path); free (image_path); asprintf (&image_path, "%s/corner-image.png", image_dir); plugin->corner_image = ply_image_new (image_path); free (image_path); asprintf (&image_path, "%s/header-image.png", image_dir); plugin->header_image = ply_image_new (image_path); free (image_path); + asprintf (&image_path, "%s/background-tile.png", image_dir); + plugin->background_tile_image = ply_image_new (image_path); + + ply_trace ("loading background tile %s", image_path); + free (image_path); + plugin->animation_dir = image_dir; alignment = ply_key_file_get_value (key_file, "two-step", "HorizontalAlignment"); if (alignment != NULL) plugin->animation_horizontal_alignment = strtod (alignment, NULL); else plugin->animation_horizontal_alignment = .5; free (alignment); alignment = ply_key_file_get_value (key_file, "two-step", "VerticalAlignment"); if (alignment != NULL) plugin->animation_vertical_alignment = strtod (alignment, NULL); else plugin->animation_vertical_alignment = .5; free (alignment); plugin->transition = PLY_PROGRESS_ANIMATION_TRANSITION_NONE; transition = ply_key_file_get_value (key_file, "two-step", "Transition"); if (transition != NULL) { if (strcmp (transition, "fade-over") == 0) plugin->transition = PLY_PROGRESS_ANIMATION_TRANSITION_FADE_OVER; else if (strcmp (transition, "cross-fade") == 0) plugin->transition = PLY_PROGRESS_ANIMATION_TRANSITION_CROSS_FADE; else if (strcmp (transition, "merge-fade") == 0) plugin->transition = PLY_PROGRESS_ANIMATION_TRANSITION_MERGE_FADE; } free (transition); transition_duration = ply_key_file_get_value (key_file, "two-step", "TransitionDuration"); @@ -626,60 +651,63 @@ free_views (ply_boot_splash_plugin_t *plugin) plugin->views = NULL; } static void destroy_plugin (ply_boot_splash_plugin_t *plugin) { if (plugin == NULL) return; ply_trace ("destroying plugin"); if (plugin->loop != NULL) { stop_animation (plugin, NULL); ply_event_loop_stop_watching_for_exit (plugin->loop, (ply_event_loop_exit_handler_t) detach_from_event_loop, plugin); detach_from_event_loop (plugin); } ply_image_free (plugin->box_image); ply_image_free (plugin->lock_image); if (plugin->corner_image != NULL) ply_image_free (plugin->corner_image); if (plugin->header_image != NULL) ply_image_free (plugin->header_image); + if (plugin->background_tile_image != NULL) + ply_image_free (plugin->background_tile_image); + free (plugin->animation_dir); free_views (plugin); free (plugin); } static void start_end_animation (ply_boot_splash_plugin_t *plugin, ply_trigger_t *trigger) { ply_trace ("starting end animation"); ply_list_node_t *node; node = ply_list_get_first_node (plugin->views); while (node != NULL) { ply_list_node_t *next_node; view_t *view; ply_trigger_t *throbber_trigger; view = ply_list_node_get_data (node); next_node = ply_list_get_next_node (plugin->views, node); ply_trigger_ignore_next_pull (trigger); if (view->throbber != NULL) { ply_trace ("stopping throbber"); view->end_trigger = trigger; throbber_trigger = ply_trigger_new (NULL); @@ -786,60 +814,67 @@ static void detach_from_event_loop (ply_boot_splash_plugin_t *plugin) { plugin->loop = NULL; } static void draw_background (view_t *view, ply_pixel_buffer_t *pixel_buffer, int x, int y, int width, int height) { ply_boot_splash_plugin_t *plugin; ply_rectangle_t area; plugin = view->plugin; area.x = x; area.y = y; area.width = width; area.height = height; if (plugin->background_start_color != plugin->background_end_color) ply_pixel_buffer_fill_with_gradient (pixel_buffer, &area, plugin->background_start_color, plugin->background_end_color); else ply_pixel_buffer_fill_with_hex_color (pixel_buffer, &area, plugin->background_start_color); + + if (view->background_image != NULL) + { + uint32_t *data; + data = ply_image_get_data (view->background_image); + ply_pixel_buffer_fill_with_argb32_data (pixel_buffer, &area, data); + } } static void on_draw (view_t *view, ply_pixel_buffer_t *pixel_buffer, int x, int y, int width, int height) { ply_boot_splash_plugin_t *plugin; ply_rectangle_t screen_area; ply_rectangle_t image_area; plugin = view->plugin; draw_background (view, pixel_buffer, x, y, width, height); ply_pixel_buffer_get_size (pixel_buffer, &screen_area); if (plugin->state == PLY_BOOT_SPLASH_DISPLAY_QUESTION_ENTRY || plugin->state == PLY_BOOT_SPLASH_DISPLAY_PASSWORD_ENTRY ) { uint32_t *box_data, *lock_data; box_data = ply_image_get_data (plugin->box_image); ply_pixel_buffer_fill_with_argb32_data (pixel_buffer, &view->box_area, box_data); @@ -970,60 +1005,70 @@ show_splash_screen (ply_boot_splash_plugin_t *plugin, ply_trace ("loading lock image"); if (!ply_image_load (plugin->lock_image)) return false; ply_trace ("loading box image"); if (!ply_image_load (plugin->box_image)) return false; if (plugin->corner_image != NULL) { ply_trace ("loading corner image"); if (!ply_image_load (plugin->corner_image)) { ply_image_free (plugin->corner_image); plugin->corner_image = NULL; } } if (plugin->header_image != NULL) { ply_trace ("loading header image"); if (!ply_image_load (plugin->header_image)) { ply_image_free (plugin->header_image); plugin->header_image = NULL; } } + if (plugin->background_tile_image != NULL) + { + ply_trace ("loading background tile image"); + if (!ply_image_load (plugin->background_tile_image)) + { + ply_image_free (plugin->background_tile_image); + plugin->background_tile_image = NULL; + } + } + if (!load_views (plugin)) { ply_trace ("couldn't load views"); return false; } ply_event_loop_watch_for_exit (loop, (ply_event_loop_exit_handler_t) detach_from_event_loop, plugin); ply_trace ("starting boot animations"); start_progress_animation (plugin); plugin->is_visible = true; return true; } static void update_status (ply_boot_splash_plugin_t *plugin, const char *status) { assert (plugin != NULL); } static void on_animation_stopped (ply_boot_splash_plugin_t *plugin) { if (plugin->idle_trigger != NULL) { -- 1.8.3.1 From 454fee71c109bfef897d9e8655d594838cd8a99b Mon Sep 17 00:00:00 2001 From: Ray Strode Date: Thu, 24 Oct 2013 09:33:17 -0400 Subject: [PATCH 4/5] two-step: add support for watermark The watermark is overlaid on top of the background but below all the other content. --- src/plugins/splash/two-step/plugin.c | 53 +++++++++++++++++++++++++++++++++++- 1 file changed, 52 insertions(+), 1 deletion(-) diff --git a/src/plugins/splash/two-step/plugin.c b/src/plugins/splash/two-step/plugin.c index 2c6d97a..5cf333f 100644 --- a/src/plugins/splash/two-step/plugin.c +++ b/src/plugins/splash/two-step/plugin.c @@ -62,78 +62,82 @@ #ifndef FRAMES_PER_SECOND #define FRAMES_PER_SECOND 30 #endif #ifndef SHOW_ANIMATION_PERCENT #define SHOW_ANIMATION_PERCENT 0.9 #endif typedef enum { PLY_BOOT_SPLASH_DISPLAY_NORMAL, PLY_BOOT_SPLASH_DISPLAY_QUESTION_ENTRY, PLY_BOOT_SPLASH_DISPLAY_PASSWORD_ENTRY } ply_boot_splash_display_type_t; typedef enum { PROGRESS_FUNCTION_TYPE_WWOODS, PROGRESS_FUNCTION_TYPE_LINEAR, } progress_function_t; typedef struct { ply_boot_splash_plugin_t *plugin; ply_pixel_display_t *display; ply_entry_t *entry; ply_animation_t *end_animation; ply_progress_animation_t *progress_animation; ply_throbber_t *throbber; ply_label_t *label; ply_label_t *message_label; - ply_rectangle_t box_area, lock_area; + ply_rectangle_t box_area, lock_area, watermark_area; ply_trigger_t *end_trigger; ply_image_t *background_image; } view_t; struct _ply_boot_splash_plugin { ply_event_loop_t *loop; ply_boot_splash_mode_t mode; ply_image_t *lock_image; ply_image_t *box_image; ply_image_t *corner_image; ply_image_t *header_image; ply_image_t *background_tile_image; + ply_image_t *watermark_image; ply_list_t *views; ply_boot_splash_display_type_t state; + double watermark_horizontal_alignment; + double watermark_vertical_alignment; + double animation_horizontal_alignment; double animation_vertical_alignment; char *animation_dir; ply_progress_animation_transition_t transition; double transition_duration; uint32_t background_start_color; uint32_t background_end_color; progress_function_t progress_function; ply_trigger_t *idle_trigger; ply_trigger_t *stop_trigger; uint32_t root_is_mounted : 1; uint32_t is_visible : 1; uint32_t is_animating : 1; uint32_t is_idle : 1; }; ply_boot_splash_plugin_interface_t * ply_boot_splash_plugin_get_interface (void); static void stop_animation (ply_boot_splash_plugin_t *plugin, ply_trigger_t *idle_trigger); static void detach_from_event_loop (ply_boot_splash_plugin_t *plugin); static void display_message (ply_boot_splash_plugin_t *plugin, const char *message); static void become_idle (ply_boot_splash_plugin_t *plugin, @@ -174,60 +178,68 @@ view_free (view_t *view) ply_entry_free (view->entry); ply_animation_free (view->end_animation); ply_progress_animation_free (view->progress_animation); ply_throbber_free (view->throbber); ply_label_free (view->label); ply_label_free (view->message_label); if (view->background_image != NULL) ply_image_free (view->background_image); free (view); } static bool view_load (view_t *view) { unsigned long screen_width, screen_height; ply_boot_splash_plugin_t *plugin; plugin = view->plugin; screen_width = ply_pixel_display_get_width (view->display); screen_height = ply_pixel_display_get_height (view->display); if (plugin->background_tile_image != NULL) { ply_trace ("tiling background to %lux%lu", screen_width, screen_height); view->background_image = ply_image_tile (plugin->background_tile_image, screen_width, screen_height); } + if (plugin->watermark_image != NULL) + { + view->watermark_area.width = ply_image_get_width (plugin->watermark_image); + view->watermark_area.height = ply_image_get_height (plugin->watermark_image); + view->watermark_area.x = screen_width * plugin->watermark_horizontal_alignment - ply_image_get_width (plugin->watermark_image) * plugin->watermark_horizontal_alignment; + view->watermark_area.y = screen_height * plugin->watermark_vertical_alignment - ply_image_get_height (plugin->watermark_image) * plugin->watermark_vertical_alignment; + } + ply_trace ("loading entry"); if (!ply_entry_load (view->entry)) return false; ply_trace ("loading animation"); if (!ply_animation_load (view->end_animation)) { ply_trace ("Default animation wouldn't load, " "falling back to old naming scheme"); /* fallback to throbber- for compatibility */ ply_animation_free (view->end_animation); view->end_animation = ply_animation_new (view->plugin->animation_dir, "throbber-"); if (!ply_animation_load (view->end_animation)) { ply_trace ("old naming scheme didn't work either"); return false; } ply_throbber_free (view->throbber); view->throbber = NULL; } ply_trace ("loading progress animation"); if (!ply_progress_animation_load (view->progress_animation)) { ply_trace ("optional progress animation wouldn't load"); ply_progress_animation_free (view->progress_animation); @@ -517,76 +529,94 @@ create_plugin (ply_key_file_t *key_file) srand ((int) ply_get_timestamp ()); plugin = calloc (1, sizeof (ply_boot_splash_plugin_t)); image_dir = ply_key_file_get_value (key_file, "two-step", "ImageDir"); ply_trace ("Using '%s' as working directory", image_dir); asprintf (&image_path, "%s/lock.png", image_dir); plugin->lock_image = ply_image_new (image_path); free (image_path); asprintf (&image_path, "%s/box.png", image_dir); plugin->box_image = ply_image_new (image_path); free (image_path); asprintf (&image_path, "%s/corner-image.png", image_dir); plugin->corner_image = ply_image_new (image_path); free (image_path); asprintf (&image_path, "%s/header-image.png", image_dir); plugin->header_image = ply_image_new (image_path); free (image_path); asprintf (&image_path, "%s/background-tile.png", image_dir); plugin->background_tile_image = ply_image_new (image_path); ply_trace ("loading background tile %s", image_path); free (image_path); + asprintf (&image_path, "%s/watermark.png", image_dir); + plugin->watermark_image = ply_image_new (image_path); + free (image_path); + plugin->animation_dir = image_dir; alignment = ply_key_file_get_value (key_file, "two-step", "HorizontalAlignment"); if (alignment != NULL) plugin->animation_horizontal_alignment = strtod (alignment, NULL); else plugin->animation_horizontal_alignment = .5; free (alignment); alignment = ply_key_file_get_value (key_file, "two-step", "VerticalAlignment"); if (alignment != NULL) plugin->animation_vertical_alignment = strtod (alignment, NULL); else plugin->animation_vertical_alignment = .5; free (alignment); + alignment = ply_key_file_get_value (key_file, "two-step", "WatermarkHorizontalAlignment"); + if (alignment != NULL) + plugin->watermark_horizontal_alignment = strtod (alignment, NULL); + else + plugin->watermark_horizontal_alignment = 1.0; + free (alignment); + + alignment = ply_key_file_get_value (key_file, "two-step", "WatermarkVerticalAlignment"); + if (alignment != NULL) + plugin->watermark_vertical_alignment = strtod (alignment, NULL); + else + plugin->watermark_vertical_alignment = .5; + free (alignment); + plugin->transition = PLY_PROGRESS_ANIMATION_TRANSITION_NONE; transition = ply_key_file_get_value (key_file, "two-step", "Transition"); if (transition != NULL) { if (strcmp (transition, "fade-over") == 0) plugin->transition = PLY_PROGRESS_ANIMATION_TRANSITION_FADE_OVER; else if (strcmp (transition, "cross-fade") == 0) plugin->transition = PLY_PROGRESS_ANIMATION_TRANSITION_CROSS_FADE; else if (strcmp (transition, "merge-fade") == 0) plugin->transition = PLY_PROGRESS_ANIMATION_TRANSITION_MERGE_FADE; } free (transition); transition_duration = ply_key_file_get_value (key_file, "two-step", "TransitionDuration"); if (transition_duration != NULL) plugin->transition_duration = strtod (transition_duration, NULL); else plugin->transition_duration = 0.0; free (transition_duration); color = ply_key_file_get_value (key_file, "two-step", "BackgroundStartColor"); if (color != NULL) plugin->background_start_color = strtol (color, NULL, 0); else plugin->background_start_color = PLYMOUTH_BACKGROUND_START_COLOR; free (color); color = ply_key_file_get_value (key_file, "two-step", "BackgroundEndColor"); @@ -654,60 +684,63 @@ free_views (ply_boot_splash_plugin_t *plugin) static void destroy_plugin (ply_boot_splash_plugin_t *plugin) { if (plugin == NULL) return; ply_trace ("destroying plugin"); if (plugin->loop != NULL) { stop_animation (plugin, NULL); ply_event_loop_stop_watching_for_exit (plugin->loop, (ply_event_loop_exit_handler_t) detach_from_event_loop, plugin); detach_from_event_loop (plugin); } ply_image_free (plugin->box_image); ply_image_free (plugin->lock_image); if (plugin->corner_image != NULL) ply_image_free (plugin->corner_image); if (plugin->header_image != NULL) ply_image_free (plugin->header_image); if (plugin->background_tile_image != NULL) ply_image_free (plugin->background_tile_image); + if (plugin->watermark_image != NULL) + ply_image_free (plugin->watermark_image); + free (plugin->animation_dir); free_views (plugin); free (plugin); } static void start_end_animation (ply_boot_splash_plugin_t *plugin, ply_trigger_t *trigger) { ply_trace ("starting end animation"); ply_list_node_t *node; node = ply_list_get_first_node (plugin->views); while (node != NULL) { ply_list_node_t *next_node; view_t *view; ply_trigger_t *throbber_trigger; view = ply_list_node_get_data (node); next_node = ply_list_get_next_node (plugin->views, node); ply_trigger_ignore_next_pull (trigger); if (view->throbber != NULL) { ply_trace ("stopping throbber"); view->end_trigger = trigger; throbber_trigger = ply_trigger_new (NULL); @@ -821,60 +854,68 @@ draw_background (view_t *view, ply_pixel_buffer_t *pixel_buffer, int x, int y, int width, int height) { ply_boot_splash_plugin_t *plugin; ply_rectangle_t area; plugin = view->plugin; area.x = x; area.y = y; area.width = width; area.height = height; if (plugin->background_start_color != plugin->background_end_color) ply_pixel_buffer_fill_with_gradient (pixel_buffer, &area, plugin->background_start_color, plugin->background_end_color); else ply_pixel_buffer_fill_with_hex_color (pixel_buffer, &area, plugin->background_start_color); if (view->background_image != NULL) { uint32_t *data; data = ply_image_get_data (view->background_image); ply_pixel_buffer_fill_with_argb32_data (pixel_buffer, &area, data); } + + if (plugin->watermark_image != NULL) + { + uint32_t *data; + + data = ply_image_get_data (plugin->watermark_image); + ply_pixel_buffer_fill_with_argb32_data (pixel_buffer, &view->watermark_area, data); + } } static void on_draw (view_t *view, ply_pixel_buffer_t *pixel_buffer, int x, int y, int width, int height) { ply_boot_splash_plugin_t *plugin; ply_rectangle_t screen_area; ply_rectangle_t image_area; plugin = view->plugin; draw_background (view, pixel_buffer, x, y, width, height); ply_pixel_buffer_get_size (pixel_buffer, &screen_area); if (plugin->state == PLY_BOOT_SPLASH_DISPLAY_QUESTION_ENTRY || plugin->state == PLY_BOOT_SPLASH_DISPLAY_PASSWORD_ENTRY ) { uint32_t *box_data, *lock_data; box_data = ply_image_get_data (plugin->box_image); ply_pixel_buffer_fill_with_argb32_data (pixel_buffer, &view->box_area, box_data); @@ -1015,60 +1056,70 @@ show_splash_screen (ply_boot_splash_plugin_t *plugin, ply_trace ("loading corner image"); if (!ply_image_load (plugin->corner_image)) { ply_image_free (plugin->corner_image); plugin->corner_image = NULL; } } if (plugin->header_image != NULL) { ply_trace ("loading header image"); if (!ply_image_load (plugin->header_image)) { ply_image_free (plugin->header_image); plugin->header_image = NULL; } } if (plugin->background_tile_image != NULL) { ply_trace ("loading background tile image"); if (!ply_image_load (plugin->background_tile_image)) { ply_image_free (plugin->background_tile_image); plugin->background_tile_image = NULL; } } + if (plugin->watermark_image != NULL) + { + ply_trace ("loading watermark image"); + if (!ply_image_load (plugin->watermark_image)) + { + ply_image_free (plugin->watermark_image); + plugin->watermark_image = NULL; + } + } + if (!load_views (plugin)) { ply_trace ("couldn't load views"); return false; } ply_event_loop_watch_for_exit (loop, (ply_event_loop_exit_handler_t) detach_from_event_loop, plugin); ply_trace ("starting boot animations"); start_progress_animation (plugin); plugin->is_visible = true; return true; } static void update_status (ply_boot_splash_plugin_t *plugin, const char *status) { assert (plugin != NULL); } static void on_animation_stopped (ply_boot_splash_plugin_t *plugin) { if (plugin->idle_trigger != NULL) { -- 1.8.3.1 From 2ce951c56b4ffa26803072789a6f8d16e4cdca3a Mon Sep 17 00:00:00 2001 From: Ray Strode Date: Fri, 25 Oct 2013 16:24:47 -0400 Subject: [PATCH 5/5] two-step: introduce delayed startup Many machines these days can boot in 5 seconds or less. In those cases, there's little point in showing a boot splash. This commit introduces a StartupDelay option to the two step plugin to prevent it from displaying anything for a few seconds. --- src/plugins/splash/two-step/plugin.c | 45 ++++++++++++++++++++++++++++++++++++ 1 file changed, 45 insertions(+) diff --git a/src/plugins/splash/two-step/plugin.c b/src/plugins/splash/two-step/plugin.c index 5cf333f..fff928c 100644 --- a/src/plugins/splash/two-step/plugin.c +++ b/src/plugins/splash/two-step/plugin.c @@ -65,135 +65,141 @@ #endif #ifndef SHOW_ANIMATION_PERCENT #define SHOW_ANIMATION_PERCENT 0.9 #endif typedef enum { PLY_BOOT_SPLASH_DISPLAY_NORMAL, PLY_BOOT_SPLASH_DISPLAY_QUESTION_ENTRY, PLY_BOOT_SPLASH_DISPLAY_PASSWORD_ENTRY } ply_boot_splash_display_type_t; typedef enum { PROGRESS_FUNCTION_TYPE_WWOODS, PROGRESS_FUNCTION_TYPE_LINEAR, } progress_function_t; typedef struct { ply_boot_splash_plugin_t *plugin; ply_pixel_display_t *display; ply_entry_t *entry; ply_animation_t *end_animation; ply_progress_animation_t *progress_animation; ply_throbber_t *throbber; ply_label_t *label; ply_label_t *message_label; ply_rectangle_t box_area, lock_area, watermark_area; ply_trigger_t *end_trigger; ply_image_t *background_image; + + uint32_t is_blank : 1; } view_t; struct _ply_boot_splash_plugin { ply_event_loop_t *loop; ply_boot_splash_mode_t mode; ply_image_t *lock_image; ply_image_t *box_image; ply_image_t *corner_image; ply_image_t *header_image; ply_image_t *background_tile_image; ply_image_t *watermark_image; ply_list_t *views; ply_boot_splash_display_type_t state; double watermark_horizontal_alignment; double watermark_vertical_alignment; double animation_horizontal_alignment; double animation_vertical_alignment; char *animation_dir; ply_progress_animation_transition_t transition; double transition_duration; uint32_t background_start_color; uint32_t background_end_color; progress_function_t progress_function; ply_trigger_t *idle_trigger; ply_trigger_t *stop_trigger; + double start_time; + double startup_delay; + uint32_t root_is_mounted : 1; uint32_t is_visible : 1; uint32_t is_animating : 1; uint32_t is_idle : 1; }; ply_boot_splash_plugin_interface_t * ply_boot_splash_plugin_get_interface (void); static void stop_animation (ply_boot_splash_plugin_t *plugin, ply_trigger_t *idle_trigger); static void detach_from_event_loop (ply_boot_splash_plugin_t *plugin); static void display_message (ply_boot_splash_plugin_t *plugin, const char *message); static void become_idle (ply_boot_splash_plugin_t *plugin, ply_trigger_t *idle_trigger); static view_t * view_new (ply_boot_splash_plugin_t *plugin, ply_pixel_display_t *display) { view_t *view; view = calloc (1, sizeof (view_t)); view->plugin = plugin; view->display = display; view->entry = ply_entry_new (plugin->animation_dir); view->end_animation = ply_animation_new (plugin->animation_dir, "animation-"); view->progress_animation = ply_progress_animation_new (plugin->animation_dir, "progress-"); view->throbber = ply_throbber_new (plugin->animation_dir, "throbber-"); ply_progress_animation_set_transition (view->progress_animation, plugin->transition, plugin->transition_duration); view->label = ply_label_new (); view->message_label = ply_label_new (); + view->is_blank = true; return view; } static void view_free (view_t *view) { ply_entry_free (view->entry); ply_animation_free (view->end_animation); ply_progress_animation_free (view->progress_animation); ply_throbber_free (view->throbber); ply_label_free (view->label); ply_label_free (view->message_label); if (view->background_image != NULL) ply_image_free (view->background_image); free (view); } static bool view_load (view_t *view) { unsigned long screen_width, screen_height; ply_boot_splash_plugin_t *plugin; plugin = view->plugin; screen_width = ply_pixel_display_get_width (view->display); @@ -494,101 +500,111 @@ view_show_prompt (view_t *view, if (prompt != NULL) { ply_label_set_text (view->label, prompt); /* We center the prompt in the middle and use 80% of the horizontal space */ int label_width = screen_width * 100 / 80; ply_label_set_alignment (view->label, PLY_LABEL_ALIGN_CENTER); ply_label_set_width (view->label, label_width); x = (screen_width - label_width) / 2; y = view->box_area.y + view->box_area.height; ply_label_show (view->label, view->display, x, y); } } static void view_hide_prompt (view_t *view) { assert (view != NULL); ply_entry_hide (view->entry); ply_label_hide (view->label); } static ply_boot_splash_plugin_t * create_plugin (ply_key_file_t *key_file) { ply_boot_splash_plugin_t *plugin; char *image_dir, *image_path; + char *startup_delay; char *alignment; char *transition; char *transition_duration; char *color; char *progress_function; srand ((int) ply_get_timestamp ()); plugin = calloc (1, sizeof (ply_boot_splash_plugin_t)); + plugin->start_time = ply_get_timestamp (); + image_dir = ply_key_file_get_value (key_file, "two-step", "ImageDir"); ply_trace ("Using '%s' as working directory", image_dir); asprintf (&image_path, "%s/lock.png", image_dir); plugin->lock_image = ply_image_new (image_path); free (image_path); asprintf (&image_path, "%s/box.png", image_dir); plugin->box_image = ply_image_new (image_path); free (image_path); asprintf (&image_path, "%s/corner-image.png", image_dir); plugin->corner_image = ply_image_new (image_path); free (image_path); asprintf (&image_path, "%s/header-image.png", image_dir); plugin->header_image = ply_image_new (image_path); free (image_path); asprintf (&image_path, "%s/background-tile.png", image_dir); plugin->background_tile_image = ply_image_new (image_path); ply_trace ("loading background tile %s", image_path); free (image_path); asprintf (&image_path, "%s/watermark.png", image_dir); plugin->watermark_image = ply_image_new (image_path); free (image_path); plugin->animation_dir = image_dir; + startup_delay = ply_key_file_get_value (key_file, "two-step", "StartupDelay"); + if (startup_delay != NULL) + plugin->startup_delay = strtod (startup_delay, NULL); + else + plugin->startup_delay = 5.0; + free (startup_delay); + alignment = ply_key_file_get_value (key_file, "two-step", "HorizontalAlignment"); if (alignment != NULL) plugin->animation_horizontal_alignment = strtod (alignment, NULL); else plugin->animation_horizontal_alignment = .5; free (alignment); alignment = ply_key_file_get_value (key_file, "two-step", "VerticalAlignment"); if (alignment != NULL) plugin->animation_vertical_alignment = strtod (alignment, NULL); else plugin->animation_vertical_alignment = .5; free (alignment); alignment = ply_key_file_get_value (key_file, "two-step", "WatermarkHorizontalAlignment"); if (alignment != NULL) plugin->watermark_horizontal_alignment = strtod (alignment, NULL); else plugin->watermark_horizontal_alignment = 1.0; free (alignment); alignment = ply_key_file_get_value (key_file, "two-step", "WatermarkVerticalAlignment"); if (alignment != NULL) plugin->watermark_vertical_alignment = strtod (alignment, NULL); else plugin->watermark_vertical_alignment = .5; free (alignment); plugin->transition = PLY_PROGRESS_ANIMATION_TRANSITION_NONE; transition = ply_key_file_get_value (key_file, "two-step", "Transition"); @@ -878,60 +894,89 @@ draw_background (view_t *view, if (view->background_image != NULL) { uint32_t *data; data = ply_image_get_data (view->background_image); ply_pixel_buffer_fill_with_argb32_data (pixel_buffer, &area, data); } if (plugin->watermark_image != NULL) { uint32_t *data; data = ply_image_get_data (plugin->watermark_image); ply_pixel_buffer_fill_with_argb32_data (pixel_buffer, &view->watermark_area, data); } } static void on_draw (view_t *view, ply_pixel_buffer_t *pixel_buffer, int x, int y, int width, int height) { ply_boot_splash_plugin_t *plugin; ply_rectangle_t screen_area; ply_rectangle_t image_area; plugin = view->plugin; + if (plugin->mode == PLY_BOOT_SPLASH_MODE_BOOT_UP) + { + double now; + + now = ply_get_timestamp (); + + if (now - plugin->start_time < plugin->startup_delay) + return; + + if (view->is_blank) + { + ply_rectangle_t clip_area; + + x = 0; + y = 0; + width = ply_pixel_display_get_width (view->display); + height = ply_pixel_display_get_height (view->display); + + clip_area.x = 0; + clip_area.y = 0; + clip_area.width = width; + clip_area.height = height; + ply_pixel_buffer_pop_clip_area (pixel_buffer); + ply_pixel_buffer_push_clip_area (pixel_buffer, + &clip_area); + view->is_blank = false; + } + } + draw_background (view, pixel_buffer, x, y, width, height); ply_pixel_buffer_get_size (pixel_buffer, &screen_area); if (plugin->state == PLY_BOOT_SPLASH_DISPLAY_QUESTION_ENTRY || plugin->state == PLY_BOOT_SPLASH_DISPLAY_PASSWORD_ENTRY ) { uint32_t *box_data, *lock_data; box_data = ply_image_get_data (plugin->box_image); ply_pixel_buffer_fill_with_argb32_data (pixel_buffer, &view->box_area, box_data); ply_entry_draw_area (view->entry, pixel_buffer, x, y, width, height); ply_label_draw_area (view->label, pixel_buffer, x, y, width, height); lock_data = ply_image_get_data (plugin->lock_image); ply_pixel_buffer_fill_with_argb32_data (pixel_buffer, &view->lock_area, lock_data); } else { if (view->throbber != NULL && !ply_throbber_is_stopped (view->throbber)) -- 1.8.3.1 From ba50f9e79da79d42ed7f50798b955ef929819daf Mon Sep 17 00:00:00 2001 From: Ray Strode Date: Fri, 8 Nov 2013 08:31:32 -0500 Subject: [PATCH] two-step: fix unlock screen The previous commit introduced a bug where the unlock screen won't get shown if it's requested within the first 5 seconds of startup. This commit fixes that by forcing a redraw if the state switches from NORMAL. --- src/plugins/splash/two-step/plugin.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/plugins/splash/two-step/plugin.c b/src/plugins/splash/two-step/plugin.c index fff928c..eaf20b3 100644 --- a/src/plugins/splash/two-step/plugin.c +++ b/src/plugins/splash/two-step/plugin.c @@ -900,61 +900,62 @@ draw_background (view_t *view, if (plugin->watermark_image != NULL) { uint32_t *data; data = ply_image_get_data (plugin->watermark_image); ply_pixel_buffer_fill_with_argb32_data (pixel_buffer, &view->watermark_area, data); } } static void on_draw (view_t *view, ply_pixel_buffer_t *pixel_buffer, int x, int y, int width, int height) { ply_boot_splash_plugin_t *plugin; ply_rectangle_t screen_area; ply_rectangle_t image_area; plugin = view->plugin; if (plugin->mode == PLY_BOOT_SPLASH_MODE_BOOT_UP) { double now; now = ply_get_timestamp (); - if (now - plugin->start_time < plugin->startup_delay) + if ((now - plugin->start_time < plugin->startup_delay) && + plugin->state == PLY_BOOT_SPLASH_DISPLAY_NORMAL) return; if (view->is_blank) { ply_rectangle_t clip_area; x = 0; y = 0; width = ply_pixel_display_get_width (view->display); height = ply_pixel_display_get_height (view->display); clip_area.x = 0; clip_area.y = 0; clip_area.width = width; clip_area.height = height; ply_pixel_buffer_pop_clip_area (pixel_buffer); ply_pixel_buffer_push_clip_area (pixel_buffer, &clip_area); view->is_blank = false; } } draw_background (view, pixel_buffer, x, y, width, height); ply_pixel_buffer_get_size (pixel_buffer, &screen_area); if (plugin->state == PLY_BOOT_SPLASH_DISPLAY_QUESTION_ENTRY || plugin->state == PLY_BOOT_SPLASH_DISPLAY_PASSWORD_ENTRY ) { uint32_t *box_data, *lock_data; -- 1.8.3.1