classic-lite

Minimalist rewrite of Łukasz Zalewski's "classic" pebble watchface
git clone https://git.instinctive.eu/classic-lite.git
Log | Files | Refs | README | LICENSE

commit ed27e5c8513ae9c139f3e2d61ab4c096d1fe8568
parent 596bdb297d526c4d4534d9c948f88e20dd35cd68
Author: Natasha Kerensikova <natacha@instinctive.eu>
Date:   Mon, 14 Dec 2015 18:04:16 +0000

Cache frame buffer to save drawing operations
Diffstat:
Msrc/classic-lite.c | 118+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 118 insertions(+), 0 deletions(-)

diff --git a/src/classic-lite.c b/src/classic-lite.c @@ -17,6 +17,8 @@ #include <pebble.h> +#define CACHE_BACKGROUND + /********************** * CONFIGURABLE STATE * **********************/ @@ -245,6 +247,88 @@ static uint8_t current_battery = 100; && (has_battery || !IS_VISIBLE(battery_color))); \ } while (0) +#ifdef CACHE_BACKGROUND +#define SCREEN_BUFFER_SIZE \ + PBL_IF_RECT_ELSE(PBL_IF_COLOR_ELSE(144 * 168, 144 * 168 / 8), 25868) + +static uint8_t background_cache[SCREEN_BUFFER_SIZE]; +static bool use_background_cache = false; + +static size_t +gbitmap_get_data_size(GBitmap *bitmap) { + GRect bounds; + if (!bitmap) return 0; + + bounds = gbitmap_get_bounds(bitmap); +#ifdef PBL_SDK_3 + GBitmapDataRowInfo row_info; + switch (gbitmap_get_format(bitmap)) { + case GBitmapFormat1Bit: + return bounds.size.w * bounds.size.h / 8; + case GBitmapFormat8Bit: + return bounds.size.w * bounds.size.h; + case GBitmapFormat8BitCircular: + row_info = gbitmap_get_data_row_info(bitmap, bounds.size.h - 1); + return (row_info.data + row_info.max_x + 1) + - gbitmap_get_data(bitmap); + default: + return 0; + } +#else + return bounds.size.w * bounds.size.h / 8; +#endif +} + +static bool +save_frame_buffer(GContext *ctx) { + GBitmap *frame_buffer = graphics_capture_frame_buffer(ctx); + + if (!frame_buffer) { + APP_LOG(APP_LOG_LEVEL_WARNING, + "Unable to capture frame buffer for saving"); + return false; + } + + if (gbitmap_get_data_size(frame_buffer) != SCREEN_BUFFER_SIZE) { + APP_LOG(APP_LOG_LEVEL_WARNING, + "Unexpected frame buffer size %u, expected %u", + gbitmap_get_data_size(frame_buffer), SCREEN_BUFFER_SIZE); + graphics_release_frame_buffer(ctx, frame_buffer); + return false; + } + + memcpy(background_cache, gbitmap_get_data(frame_buffer), + sizeof background_cache); + use_background_cache = true; + graphics_release_frame_buffer(ctx, frame_buffer); + return true; +} + +static bool +restore_frame_buffer(GContext *ctx) { + GBitmap *frame_buffer = graphics_capture_frame_buffer(ctx); + + if (!frame_buffer) { + APP_LOG(APP_LOG_LEVEL_WARNING, + "Unable to capture frame buffer for restore"); + return false; + } + + if (gbitmap_get_data_size(frame_buffer) != SCREEN_BUFFER_SIZE) { + APP_LOG(APP_LOG_LEVEL_WARNING, + "Unexpected frame buffer size %u, expected %u", + gbitmap_get_data_size(frame_buffer), SCREEN_BUFFER_SIZE); + graphics_release_frame_buffer(ctx, frame_buffer); + return false; + } + + memcpy(gbitmap_get_data(frame_buffer), background_cache, + sizeof background_cache); + graphics_release_frame_buffer(ctx, frame_buffer); + return true; +} +#endif + #ifdef PBL_RECT static void point_at_angle(GRect *rect, int32_t angle, GPoint *output, int *horizontal) { @@ -278,6 +362,10 @@ background_layer_draw(Layer *layer, GContext *ctx) { (void)layer; +#ifdef CACHE_BACKGROUND + if (use_background_cache && restore_frame_buffer(ctx)) return; +#endif + if (IS_VISIBLE(minute_mark_color)) { graphics_context_set_stroke_color(ctx, minute_mark_color); INSET_RECT(rect, bounds, 5); @@ -347,6 +435,10 @@ background_layer_draw(Layer *layer, GContext *ctx) { graphics_draw_rect(ctx, rect); #endif } + +#ifdef CACHE_BACKGROUND + save_frame_buffer(ctx); +#endif } #else static GPoint @@ -376,6 +468,10 @@ background_layer_draw(Layer *layer, GContext *ctx) { (void)layer; +#ifdef CACHE_BACKGROUND + if (use_background_cache && restore_frame_buffer(ctx)) return; +#endif + if (IS_VISIBLE(minute_mark_color)) { graphics_context_set_stroke_color(ctx, minute_mark_color); INSET_RECT(rect, bounds, 5); @@ -407,6 +503,10 @@ background_layer_draw(Layer *layer, GContext *ctx) { graphics_context_set_stroke_color(ctx, inner_rectangle_color); graphics_draw_circle(ctx, center, radius - 35); } + +#ifdef CACHE_BACKGROUND + save_frame_buffer(ctx); +#endif } #endif @@ -426,6 +526,10 @@ hand_layer_draw(Layer *layer, GContext *ctx) { gpath_draw_filled(ctx, hour_hand_path); gpath_draw_outline(ctx, hour_hand_path); +#ifdef CACHE_BACKGROUND + if (!use_background_cache) return; +#endif + graphics_context_set_fill_color(ctx, background_color); graphics_fill_circle(ctx, center, 2); graphics_context_set_fill_color(ctx, hand_color); @@ -596,10 +700,17 @@ inbox_received_handler(DictionaryIterator *iterator, void *context) { } } +#ifdef CACHE_BACKGROUND + use_background_cache = !IS_VISIBLE(inner_rectangle_color) + && !IS_VISIBLE(hour_mark_color) + && !IS_VISIBLE(minute_mark_color); + layer_set_hidden(background_layer, use_background_cache); +#else layer_set_hidden(background_layer, !IS_VISIBLE(inner_rectangle_color) && !IS_VISIBLE(hour_mark_color) && !IS_VISIBLE(minute_mark_color)); +#endif ICON_LAYER_SET_HIDDEN; @@ -632,10 +743,17 @@ window_load(Window *window) { background_layer = layer_create(bounds); layer_set_update_proc(background_layer, &background_layer_draw); +#ifdef CACHE_BACKGROUND + use_background_cache = !IS_VISIBLE(inner_rectangle_color) + && !IS_VISIBLE(hour_mark_color) + && !IS_VISIBLE(minute_mark_color); + layer_set_hidden(background_layer, use_background_cache); +#else layer_set_hidden(background_layer, !IS_VISIBLE(inner_rectangle_color) && !IS_VISIBLE(hour_mark_color) && !IS_VISIBLE(minute_mark_color)); +#endif layer_add_child(window_layer, background_layer); text_layer = text_layer_create(GRect(