diff --git a/appinfo.json b/appinfo.json index e9a950d..1c531c8 100644 --- a/appinfo.json +++ b/appinfo.json @@ -18,20 +18,18 @@ "configurable" ], "companyName": "Nicko Guyer", - "longName": "Engineering", + "longName": "Engineering-shadow", "projectType": "native", "resources": { "media": [] }, "sdkVersion": "3", - "shortName": "Engineering", + "shortName": "Engineering-shadow", "targetPlatforms": [ - "aplite", - "basalt", - "chalk" + "basalt" ], - "uuid": "ff541ca4-a444-4513-879a-35ff9ec48a1b", - "versionLabel": "1.6", + "uuid": "3f2fc7bd-fe40-465f-96fb-9ddf40c6e1f3", + "versionLabel": "1.7", "watchapp": { "watchface": true } diff --git a/engineering-shadow.png b/engineering-shadow.png new file mode 100644 index 0000000..03bd8c3 Binary files /dev/null and b/engineering-shadow.png differ diff --git a/engineering.png b/engineering.png new file mode 100644 index 0000000..5c6c1cf Binary files /dev/null and b/engineering.png differ diff --git a/src/engineering.c b/src/engineering.c index d0d80f6..b089749 100644 --- a/src/engineering.c +++ b/src/engineering.c @@ -1,6 +1,7 @@ #include #include #include "engineering.h" +#include "libshadow.h" static Window *window; static Layer *s_simple_bg_layer, *s_date_layer, *s_hands_layer; @@ -15,156 +16,158 @@ static uint8_t s_sync_buffer[64]; static GColor gcolor_background, gcolor_hour_marks, gcolor_minute_marks, gcolor_numbers, gcolor_hour_hand, gcolor_minute_hand, gcolor_second_hand; static bool b_show_numbers, b_show_temperature, b_show_date, b_show_second_hand; +static GShadow shadow_hour_marks, shadow_minute_marks, shadow_numbers, shadow_hour_hand, shadow_minute_hand, shadow_second_hand, shadow_dot; + static void load_persisted_values() { - // SHOW_NUMBERS - if (persist_exists(KEY_SHOW_NUMBERS)) { - b_show_numbers = persist_read_int(KEY_SHOW_NUMBERS); - } - - // SHOW_SECOND_HAND - if (persist_exists(KEY_SHOW_SECOND_HAND)) { - b_show_second_hand = persist_read_int(KEY_SHOW_SECOND_HAND); - } - - // SHOW_TEMPERATURE - if (persist_exists(KEY_SHOW_TEMPERATURE)) { - b_show_temperature = persist_read_int(KEY_SHOW_TEMPERATURE); - } - - // SHOW_DATE - if (persist_exists(KEY_SHOW_DATE)) { - b_show_date = persist_read_int(KEY_SHOW_DATE); - } - - // COLOR_BACKGROUND - if (persist_exists(KEY_COLOR_BACKGROUND)) { - int color_hex = persist_read_int(KEY_COLOR_BACKGROUND); - gcolor_background = GColorFromHEX(color_hex); - window_set_background_color(window, gcolor_background); - } - - // COLOR_HOUR_MARKS - if (persist_exists(KEY_COLOR_HOUR_MARKS)) { - int color_hex = persist_read_int(KEY_COLOR_HOUR_MARKS); - gcolor_hour_marks = GColorFromHEX(color_hex); - } - - // COLOR_MINUTE_MARKS - if (persist_exists(KEY_COLOR_MINUTE_MARKS)) { - int color_hex = persist_read_int(KEY_COLOR_MINUTE_MARKS); - gcolor_minute_marks = GColorFromHEX(color_hex); - } - - // COLOR_LABEL - if (persist_exists(KEY_COLOR_LABEL)) { - int color_hex = persist_read_int(KEY_COLOR_LABEL); - gcolor_numbers = GColorFromHEX(color_hex); - } - - // COLOR_HOUR_HAND - if (persist_exists(KEY_COLOR_HOUR_HAND)) { - int color_hex = persist_read_int(KEY_COLOR_HOUR_HAND); - gcolor_hour_hand = GColorFromHEX(color_hex); - } - - // COLOR_MINUTE_HAND - if (persist_exists(KEY_COLOR_MINUTE_HAND)) { - int color_hex = persist_read_int(KEY_COLOR_MINUTE_HAND); - gcolor_minute_hand = GColorFromHEX(color_hex); - } - - // COLOR_SECOND_HAND - if (persist_exists(KEY_COLOR_SECOND_HAND)) { - int color_hex = persist_read_int(KEY_COLOR_SECOND_HAND); - gcolor_second_hand = GColorFromHEX(color_hex); - } + // SHOW_NUMBERS + if (persist_exists(KEY_SHOW_NUMBERS)) { + b_show_numbers = persist_read_int(KEY_SHOW_NUMBERS); + } + + // SHOW_SECOND_HAND + if (persist_exists(KEY_SHOW_SECOND_HAND)) { + b_show_second_hand = persist_read_int(KEY_SHOW_SECOND_HAND); + } + + // SHOW_TEMPERATURE + if (persist_exists(KEY_SHOW_TEMPERATURE)) { + b_show_temperature = persist_read_int(KEY_SHOW_TEMPERATURE); + } + + // SHOW_DATE + if (persist_exists(KEY_SHOW_DATE)) { + b_show_date = persist_read_int(KEY_SHOW_DATE); + } + + // COLOR_BACKGROUND + if (persist_exists(KEY_COLOR_BACKGROUND)) { + int color_hex = persist_read_int(KEY_COLOR_BACKGROUND); + gcolor_background = GColorFromHEX(color_hex); + window_set_background_color(window, gcolor_background); + } + + // COLOR_HOUR_MARKS + if (persist_exists(KEY_COLOR_HOUR_MARKS)) { + int color_hex = persist_read_int(KEY_COLOR_HOUR_MARKS); + gcolor_hour_marks = GColorFromHEX(color_hex); + } + + // COLOR_MINUTE_MARKS + if (persist_exists(KEY_COLOR_MINUTE_MARKS)) { + int color_hex = persist_read_int(KEY_COLOR_MINUTE_MARKS); + gcolor_minute_marks = GColorFromHEX(color_hex); + } + + // COLOR_LABEL + if (persist_exists(KEY_COLOR_LABEL)) { + int color_hex = persist_read_int(KEY_COLOR_LABEL); + gcolor_numbers = GColorFromHEX(color_hex); + } + + // COLOR_HOUR_HAND + if (persist_exists(KEY_COLOR_HOUR_HAND)) { + int color_hex = persist_read_int(KEY_COLOR_HOUR_HAND); + gcolor_hour_hand = GColorFromHEX(color_hex); + } + + // COLOR_MINUTE_HAND + if (persist_exists(KEY_COLOR_MINUTE_HAND)) { + int color_hex = persist_read_int(KEY_COLOR_MINUTE_HAND); + gcolor_minute_hand = GColorFromHEX(color_hex); + } + + // COLOR_SECOND_HAND + if (persist_exists(KEY_COLOR_SECOND_HAND)) { + int color_hex = persist_read_int(KEY_COLOR_SECOND_HAND); + gcolor_second_hand = GColorFromHEX(color_hex); + } } static void inbox_received_handler(DictionaryIterator *iter, void *context) { - Tuple *temperature_t = dict_find(iter, KEY_TEMPERATURE); - if(temperature_t) { - snprintf(s_temp_buffer, 5, "%d°", temperature_t->value->int16); - APP_LOG(APP_LOG_LEVEL_INFO, s_temp_buffer); - } - - Tuple *show_numbers_t = dict_find(iter, KEY_SHOW_NUMBERS); - if(show_numbers_t) { - APP_LOG(APP_LOG_LEVEL_INFO, "Show numbers %d", show_numbers_t->value->uint8); - b_show_numbers = show_numbers_t->value->uint8; - persist_write_int(KEY_SHOW_NUMBERS, b_show_numbers); - } - - Tuple *show_date_t = dict_find(iter, KEY_SHOW_DATE); - if(show_date_t) { - APP_LOG(APP_LOG_LEVEL_INFO, "Show date %d", show_date_t->value->uint8); - b_show_date = show_date_t->value->uint8; - persist_write_int(KEY_SHOW_DATE, show_date_t->value->uint8); - } - - Tuple *show_temperature_t = dict_find(iter, KEY_SHOW_TEMPERATURE); - if(show_temperature_t) { - APP_LOG(APP_LOG_LEVEL_INFO, "Show temperature %d", show_temperature_t->value->uint8); - b_show_temperature = show_temperature_t->value->uint8; - persist_write_int(KEY_SHOW_TEMPERATURE, b_show_temperature); - } - - Tuple *show_second_hand_t = dict_find(iter, KEY_SHOW_SECOND_HAND); - if(show_second_hand_t) { - APP_LOG(APP_LOG_LEVEL_INFO, "Show second hand %d", show_second_hand_t->value->uint8); - b_show_second_hand = show_second_hand_t->value->uint8; - persist_write_int(KEY_SHOW_SECOND_HAND, show_second_hand_t->value->uint8); - } - - Tuple *color_background_t = dict_find(iter, KEY_COLOR_BACKGROUND); - if(color_background_t) { - APP_LOG(APP_LOG_LEVEL_INFO, "Background color %lu", color_background_t->value->int32); - gcolor_background = GColorFromHEX(color_background_t->value->int32); - window_set_background_color(window, gcolor_background); - persist_write_int(KEY_COLOR_BACKGROUND, color_background_t->value->int32); - } - - Tuple *color_label_t = dict_find(iter, KEY_COLOR_LABEL); - if(color_label_t) { - APP_LOG(APP_LOG_LEVEL_INFO, "Label color %lu", color_label_t->value->int32); - gcolor_numbers = GColorFromHEX(color_label_t->value->int32); - persist_write_int(KEY_COLOR_LABEL, color_label_t->value->int32); - } - - Tuple *color_hour_marks_t = dict_find(iter, KEY_COLOR_HOUR_MARKS); - if(color_hour_marks_t) { - APP_LOG(APP_LOG_LEVEL_INFO, "Hour mark color %lu", color_hour_marks_t->value->int32); - gcolor_hour_marks = GColorFromHEX(color_hour_marks_t->value->int32); - persist_write_int(KEY_COLOR_HOUR_MARKS, color_hour_marks_t->value->int32); - } - - Tuple *color_minute_marks_t = dict_find(iter, KEY_COLOR_MINUTE_MARKS); - if(color_minute_marks_t) { - APP_LOG(APP_LOG_LEVEL_INFO, "Minute mark color %lu", color_minute_marks_t->value->int32); - gcolor_minute_marks = GColorFromHEX(color_minute_marks_t->value->int32); - persist_write_int(KEY_COLOR_MINUTE_MARKS, color_minute_marks_t->value->int32); - } - - Tuple *color_hour_hand_t = dict_find(iter, KEY_COLOR_HOUR_HAND); - if(color_hour_hand_t) { - APP_LOG(APP_LOG_LEVEL_INFO, "Hour hand color %lu", color_hour_hand_t->value->int32); - gcolor_hour_hand = GColorFromHEX(color_hour_hand_t->value->int32); - persist_write_int(KEY_COLOR_HOUR_HAND, color_hour_hand_t->value->int32); - } - - Tuple *color_minute_hand_t = dict_find(iter, KEY_COLOR_MINUTE_HAND); - if(color_minute_hand_t) { - APP_LOG(APP_LOG_LEVEL_INFO, "Minute hand color %lu", color_minute_hand_t->value->int32); - gcolor_minute_hand = GColorFromHEX(color_minute_hand_t->value->int32); - persist_write_int(KEY_COLOR_MINUTE_HAND, color_minute_hand_t->value->int32); - } - - Tuple *color_second_hand_t = dict_find(iter, KEY_COLOR_SECOND_HAND); - if(color_second_hand_t) { - APP_LOG(APP_LOG_LEVEL_INFO, "Second hand color %lu", color_second_hand_t->value->int32); - gcolor_second_hand = GColorFromHEX(color_second_hand_t->value->int32); - persist_write_int(KEY_COLOR_SECOND_HAND, color_second_hand_t->value->int32); - } + Tuple *temperature_t = dict_find(iter, KEY_TEMPERATURE); + if(temperature_t) { + snprintf(s_temp_buffer, 5, "%d°", temperature_t->value->int16); + APP_LOG(APP_LOG_LEVEL_INFO, s_temp_buffer); + } + + Tuple *show_numbers_t = dict_find(iter, KEY_SHOW_NUMBERS); + if(show_numbers_t) { + APP_LOG(APP_LOG_LEVEL_INFO, "Show numbers %d", show_numbers_t->value->uint8); + b_show_numbers = show_numbers_t->value->uint8; + persist_write_int(KEY_SHOW_NUMBERS, b_show_numbers); + } + + Tuple *show_date_t = dict_find(iter, KEY_SHOW_DATE); + if(show_date_t) { + APP_LOG(APP_LOG_LEVEL_INFO, "Show date %d", show_date_t->value->uint8); + b_show_date = show_date_t->value->uint8; + persist_write_int(KEY_SHOW_DATE, show_date_t->value->uint8); + } + + Tuple *show_temperature_t = dict_find(iter, KEY_SHOW_TEMPERATURE); + if(show_temperature_t) { + APP_LOG(APP_LOG_LEVEL_INFO, "Show temperature %d", show_temperature_t->value->uint8); + b_show_temperature = show_temperature_t->value->uint8; + persist_write_int(KEY_SHOW_TEMPERATURE, b_show_temperature); + } + + Tuple *show_second_hand_t = dict_find(iter, KEY_SHOW_SECOND_HAND); + if(show_second_hand_t) { + APP_LOG(APP_LOG_LEVEL_INFO, "Show second hand %d", show_second_hand_t->value->uint8); + b_show_second_hand = show_second_hand_t->value->uint8; + persist_write_int(KEY_SHOW_SECOND_HAND, show_second_hand_t->value->uint8); + } + + Tuple *color_background_t = dict_find(iter, KEY_COLOR_BACKGROUND); + if(color_background_t) { + APP_LOG(APP_LOG_LEVEL_INFO, "Background color %lu", color_background_t->value->int32); + gcolor_background = GColorFromHEX(color_background_t->value->int32); + window_set_background_color(window, gcolor_background); + persist_write_int(KEY_COLOR_BACKGROUND, color_background_t->value->int32); + } + + Tuple *color_label_t = dict_find(iter, KEY_COLOR_LABEL); + if(color_label_t) { + APP_LOG(APP_LOG_LEVEL_INFO, "Label color %lu", color_label_t->value->int32); + gcolor_numbers = GColorFromHEX(color_label_t->value->int32); + persist_write_int(KEY_COLOR_LABEL, color_label_t->value->int32); + } + + Tuple *color_hour_marks_t = dict_find(iter, KEY_COLOR_HOUR_MARKS); + if(color_hour_marks_t) { + APP_LOG(APP_LOG_LEVEL_INFO, "Hour mark color %lu", color_hour_marks_t->value->int32); + gcolor_hour_marks = GColorFromHEX(color_hour_marks_t->value->int32); + persist_write_int(KEY_COLOR_HOUR_MARKS, color_hour_marks_t->value->int32); + } + + Tuple *color_minute_marks_t = dict_find(iter, KEY_COLOR_MINUTE_MARKS); + if(color_minute_marks_t) { + APP_LOG(APP_LOG_LEVEL_INFO, "Minute mark color %lu", color_minute_marks_t->value->int32); + gcolor_minute_marks = GColorFromHEX(color_minute_marks_t->value->int32); + persist_write_int(KEY_COLOR_MINUTE_MARKS, color_minute_marks_t->value->int32); + } + + Tuple *color_hour_hand_t = dict_find(iter, KEY_COLOR_HOUR_HAND); + if(color_hour_hand_t) { + APP_LOG(APP_LOG_LEVEL_INFO, "Hour hand color %lu", color_hour_hand_t->value->int32); + gcolor_hour_hand = GColorFromHEX(color_hour_hand_t->value->int32); + persist_write_int(KEY_COLOR_HOUR_HAND, color_hour_hand_t->value->int32); + } + + Tuple *color_minute_hand_t = dict_find(iter, KEY_COLOR_MINUTE_HAND); + if(color_minute_hand_t) { + APP_LOG(APP_LOG_LEVEL_INFO, "Minute hand color %lu", color_minute_hand_t->value->int32); + gcolor_minute_hand = GColorFromHEX(color_minute_hand_t->value->int32); + persist_write_int(KEY_COLOR_MINUTE_HAND, color_minute_hand_t->value->int32); + } + + Tuple *color_second_hand_t = dict_find(iter, KEY_COLOR_SECOND_HAND); + if(color_second_hand_t) { + APP_LOG(APP_LOG_LEVEL_INFO, "Second hand color %lu", color_second_hand_t->value->int32); + gcolor_second_hand = GColorFromHEX(color_second_hand_t->value->int32); + persist_write_int(KEY_COLOR_SECOND_HAND, color_second_hand_t->value->int32); + } } static bool color_hour_marks(GDrawCommand *command, uint32_t index, void *context) { @@ -190,246 +193,326 @@ static int32_t get_angle_for_minute(int hour) { static void bg_update_proc(Layer *layer, GContext *ctx) { - GRect bounds = layer_get_bounds(layer); - GRect frame = grect_inset(bounds, GEdgeInsets(4 * INSET)); - GRect inner_hour_frame = grect_inset(bounds, GEdgeInsets((4 * INSET) + 8)); - GRect inner_minute_frame = grect_inset(bounds, GEdgeInsets((4 * INSET) + 6)); - - graphics_context_set_stroke_color(ctx, gcolor_hour_marks); - graphics_context_set_stroke_width(ctx, 3); - - // Hours marks - for(int i = 0; i < 12; i++) { - int hour_angle = get_angle_for_hour(i); - GPoint p0 = gpoint_from_polar(frame, GOvalScaleModeFitCircle, DEG_TO_TRIGANGLE(hour_angle)); - GPoint p1 = gpoint_from_polar(inner_hour_frame, GOvalScaleModeFitCircle, DEG_TO_TRIGANGLE(hour_angle)); - graphics_draw_line(ctx, p0, p1); - } - - // Minute Marks - graphics_context_set_stroke_color(ctx, gcolor_minute_marks); - graphics_context_set_stroke_width(ctx, 1); - for(int i = 0; i < 60; i++) { - if (i % 5) { - int minute_angle = get_angle_for_minute(i); - GPoint p0 = gpoint_from_polar(frame, GOvalScaleModeFitCircle, DEG_TO_TRIGANGLE(minute_angle)); - GPoint p1 = gpoint_from_polar(inner_minute_frame, GOvalScaleModeFitCircle, DEG_TO_TRIGANGLE(minute_angle)); - graphics_draw_line(ctx, p0, p1); - } - } - - // numbers - if (b_show_numbers) { - graphics_context_set_text_color(ctx, gcolor_numbers); - + GRect bounds = layer_get_bounds(layer); + GRect frame = grect_inset(bounds, GEdgeInsets(4 * INSET)); + GRect inner_hour_frame = grect_inset(bounds, GEdgeInsets((4 * INSET) + 8)); + GRect inner_minute_frame = grect_inset(bounds, GEdgeInsets((4 * INSET) + 6)); + + // numbers + if (b_show_numbers) { + switch_to_shadow_ctx (ctx);{ + graphics_context_set_text_color(ctx, gcolor (shadow_numbers)); +#ifdef PBL_RECT + graphics_draw_text(ctx, "12", fonts_get_system_font(FONT_KEY_GOTHIC_24_BOLD), GRect(63, 18, 20, 20), GTextOverflowModeWordWrap, GTextAlignmentCenter, NULL); + graphics_draw_text(ctx, "1", fonts_get_system_font(FONT_KEY_GOTHIC_24_BOLD), GRect(85, 23, 20, 20), GTextOverflowModeWordWrap, GTextAlignmentRight, NULL); + graphics_draw_text(ctx, "2", fonts_get_system_font(FONT_KEY_GOTHIC_24_BOLD), GRect(104, 43, 20, 20), GTextOverflowModeWordWrap, GTextAlignmentRight, NULL); + graphics_draw_text(ctx, "3", fonts_get_system_font(FONT_KEY_GOTHIC_24_BOLD), GRect(112, 68, 20, 20), GTextOverflowModeWordWrap, GTextAlignmentRight, NULL); + graphics_draw_text(ctx, "4", fonts_get_system_font(FONT_KEY_GOTHIC_24_BOLD), GRect(104, 93, 20, 20), GTextOverflowModeWordWrap, GTextAlignmentRight, NULL); + graphics_draw_text(ctx, "5", fonts_get_system_font(FONT_KEY_GOTHIC_24_BOLD), GRect(85, 110, 20, 20), GTextOverflowModeWordWrap, GTextAlignmentRight, NULL); + graphics_draw_text(ctx, "6", fonts_get_system_font(FONT_KEY_GOTHIC_24_BOLD), GRect(62, 118, 20, 20), GTextOverflowModeWordWrap, GTextAlignmentCenter, NULL); + graphics_draw_text(ctx, "7", fonts_get_system_font(FONT_KEY_GOTHIC_24_BOLD), GRect(39, 110, 20, 20), GTextOverflowModeWordWrap, GTextAlignmentLeft, NULL); + graphics_draw_text(ctx, "8", fonts_get_system_font(FONT_KEY_GOTHIC_24_BOLD), GRect(20, 93, 20, 20), GTextOverflowModeWordWrap, GTextAlignmentLeft, NULL); + graphics_draw_text(ctx, "9", fonts_get_system_font(FONT_KEY_GOTHIC_24_BOLD), GRect(14, 68, 20, 20), GTextOverflowModeWordWrap, GTextAlignmentLeft, NULL); + graphics_draw_text(ctx, "10", fonts_get_system_font(FONT_KEY_GOTHIC_24_BOLD), GRect(20, 43, 20, 20), GTextOverflowModeWordWrap, GTextAlignmentLeft, NULL); + graphics_draw_text(ctx, "11", fonts_get_system_font(FONT_KEY_GOTHIC_24_BOLD), GRect(39, 23, 20, 20), GTextOverflowModeWordWrap, GTextAlignmentLeft, NULL); +#else + graphics_draw_text(ctx, "12", fonts_get_system_font(FONT_KEY_GOTHIC_24_BOLD), GRect(80, 10, 20, 20), GTextOverflowModeWordWrap, GTextAlignmentCenter, NULL); + graphics_draw_text(ctx, "1", fonts_get_system_font(FONT_KEY_GOTHIC_24_BOLD), GRect(107, 20, 20, 20), GTextOverflowModeWordWrap, GTextAlignmentRight, NULL); + graphics_draw_text(ctx, "2", fonts_get_system_font(FONT_KEY_GOTHIC_24_BOLD), GRect(130, 43, 20, 20), GTextOverflowModeWordWrap, GTextAlignmentRight, NULL); + graphics_draw_text(ctx, "3", fonts_get_system_font(FONT_KEY_GOTHIC_24_BOLD), GRect(140, 74, 20, 20), GTextOverflowModeWordWrap, GTextAlignmentRight, NULL); + graphics_draw_text(ctx, "4", fonts_get_system_font(FONT_KEY_GOTHIC_24_BOLD), GRect(130, 106, 20, 20), GTextOverflowModeWordWrap, GTextAlignmentRight, NULL); + graphics_draw_text(ctx, "5", fonts_get_system_font(FONT_KEY_GOTHIC_24_BOLD), GRect(107, 126, 20, 20), GTextOverflowModeWordWrap, GTextAlignmentRight, NULL); + graphics_draw_text(ctx, "6", fonts_get_system_font(FONT_KEY_GOTHIC_24_BOLD), GRect(81, 136, 20, 20), GTextOverflowModeWordWrap, GTextAlignmentCenter, NULL); + graphics_draw_text(ctx, "7", fonts_get_system_font(FONT_KEY_GOTHIC_24_BOLD), GRect(53, 124, 20, 20), GTextOverflowModeWordWrap, GTextAlignmentLeft, NULL); + graphics_draw_text(ctx, "8", fonts_get_system_font(FONT_KEY_GOTHIC_24_BOLD), GRect(29, 106, 20, 20), GTextOverflowModeWordWrap, GTextAlignmentLeft, NULL); + graphics_draw_text(ctx, "9", fonts_get_system_font(FONT_KEY_GOTHIC_24_BOLD), GRect(20, 74, 20, 20), GTextOverflowModeWordWrap, GTextAlignmentLeft, NULL); + graphics_draw_text(ctx, "10", fonts_get_system_font(FONT_KEY_GOTHIC_24_BOLD), GRect(28, 42, 20, 20), GTextOverflowModeWordWrap, GTextAlignmentLeft, NULL); + graphics_draw_text(ctx, "11", fonts_get_system_font(FONT_KEY_GOTHIC_24_BOLD), GRect(50, 22, 20, 20), GTextOverflowModeWordWrap, GTextAlignmentLeft, NULL); +#endif + }revert_to_fb_ctx (ctx); + graphics_context_set_text_color(ctx, gcolor_numbers); #ifdef PBL_RECT - graphics_draw_text(ctx, "12", fonts_get_system_font(FONT_KEY_GOTHIC_24_BOLD), GRect(63, 18, 20, 20), GTextOverflowModeWordWrap, GTextAlignmentCenter, NULL); - graphics_draw_text(ctx, "1", fonts_get_system_font(FONT_KEY_GOTHIC_24_BOLD), GRect(85, 23, 20, 20), GTextOverflowModeWordWrap, GTextAlignmentRight, NULL); - graphics_draw_text(ctx, "2", fonts_get_system_font(FONT_KEY_GOTHIC_24_BOLD), GRect(104, 43, 20, 20), GTextOverflowModeWordWrap, GTextAlignmentRight, NULL); - graphics_draw_text(ctx, "3", fonts_get_system_font(FONT_KEY_GOTHIC_24_BOLD), GRect(112, 68, 20, 20), GTextOverflowModeWordWrap, GTextAlignmentRight, NULL); - graphics_draw_text(ctx, "4", fonts_get_system_font(FONT_KEY_GOTHIC_24_BOLD), GRect(104, 93, 20, 20), GTextOverflowModeWordWrap, GTextAlignmentRight, NULL); - graphics_draw_text(ctx, "5", fonts_get_system_font(FONT_KEY_GOTHIC_24_BOLD), GRect(85, 110, 20, 20), GTextOverflowModeWordWrap, GTextAlignmentRight, NULL); - graphics_draw_text(ctx, "6", fonts_get_system_font(FONT_KEY_GOTHIC_24_BOLD), GRect(62, 118, 20, 20), GTextOverflowModeWordWrap, GTextAlignmentCenter, NULL); - graphics_draw_text(ctx, "7", fonts_get_system_font(FONT_KEY_GOTHIC_24_BOLD), GRect(39, 110, 20, 20), GTextOverflowModeWordWrap, GTextAlignmentLeft, NULL); - graphics_draw_text(ctx, "8", fonts_get_system_font(FONT_KEY_GOTHIC_24_BOLD), GRect(20, 93, 20, 20), GTextOverflowModeWordWrap, GTextAlignmentLeft, NULL); - graphics_draw_text(ctx, "9", fonts_get_system_font(FONT_KEY_GOTHIC_24_BOLD), GRect(14, 68, 20, 20), GTextOverflowModeWordWrap, GTextAlignmentLeft, NULL); - graphics_draw_text(ctx, "10", fonts_get_system_font(FONT_KEY_GOTHIC_24_BOLD), GRect(20, 43, 20, 20), GTextOverflowModeWordWrap, GTextAlignmentLeft, NULL); - graphics_draw_text(ctx, "11", fonts_get_system_font(FONT_KEY_GOTHIC_24_BOLD), GRect(39, 23, 20, 20), GTextOverflowModeWordWrap, GTextAlignmentLeft, NULL); + graphics_draw_text(ctx, "12", fonts_get_system_font(FONT_KEY_GOTHIC_24_BOLD), GRect(63, 18, 20, 20), GTextOverflowModeWordWrap, GTextAlignmentCenter, NULL); + graphics_draw_text(ctx, "1", fonts_get_system_font(FONT_KEY_GOTHIC_24_BOLD), GRect(85, 23, 20, 20), GTextOverflowModeWordWrap, GTextAlignmentRight, NULL); + graphics_draw_text(ctx, "2", fonts_get_system_font(FONT_KEY_GOTHIC_24_BOLD), GRect(104, 43, 20, 20), GTextOverflowModeWordWrap, GTextAlignmentRight, NULL); + graphics_draw_text(ctx, "3", fonts_get_system_font(FONT_KEY_GOTHIC_24_BOLD), GRect(112, 68, 20, 20), GTextOverflowModeWordWrap, GTextAlignmentRight, NULL); + graphics_draw_text(ctx, "4", fonts_get_system_font(FONT_KEY_GOTHIC_24_BOLD), GRect(104, 93, 20, 20), GTextOverflowModeWordWrap, GTextAlignmentRight, NULL); + graphics_draw_text(ctx, "5", fonts_get_system_font(FONT_KEY_GOTHIC_24_BOLD), GRect(85, 110, 20, 20), GTextOverflowModeWordWrap, GTextAlignmentRight, NULL); + graphics_draw_text(ctx, "6", fonts_get_system_font(FONT_KEY_GOTHIC_24_BOLD), GRect(62, 118, 20, 20), GTextOverflowModeWordWrap, GTextAlignmentCenter, NULL); + graphics_draw_text(ctx, "7", fonts_get_system_font(FONT_KEY_GOTHIC_24_BOLD), GRect(39, 110, 20, 20), GTextOverflowModeWordWrap, GTextAlignmentLeft, NULL); + graphics_draw_text(ctx, "8", fonts_get_system_font(FONT_KEY_GOTHIC_24_BOLD), GRect(20, 93, 20, 20), GTextOverflowModeWordWrap, GTextAlignmentLeft, NULL); + graphics_draw_text(ctx, "9", fonts_get_system_font(FONT_KEY_GOTHIC_24_BOLD), GRect(14, 68, 20, 20), GTextOverflowModeWordWrap, GTextAlignmentLeft, NULL); + graphics_draw_text(ctx, "10", fonts_get_system_font(FONT_KEY_GOTHIC_24_BOLD), GRect(20, 43, 20, 20), GTextOverflowModeWordWrap, GTextAlignmentLeft, NULL); + graphics_draw_text(ctx, "11", fonts_get_system_font(FONT_KEY_GOTHIC_24_BOLD), GRect(39, 23, 20, 20), GTextOverflowModeWordWrap, GTextAlignmentLeft, NULL); #else - graphics_draw_text(ctx, "12", fonts_get_system_font(FONT_KEY_GOTHIC_24_BOLD), GRect(80, 10, 20, 20), GTextOverflowModeWordWrap, GTextAlignmentCenter, NULL); - graphics_draw_text(ctx, "1", fonts_get_system_font(FONT_KEY_GOTHIC_24_BOLD), GRect(107, 20, 20, 20), GTextOverflowModeWordWrap, GTextAlignmentRight, NULL); - graphics_draw_text(ctx, "2", fonts_get_system_font(FONT_KEY_GOTHIC_24_BOLD), GRect(130, 43, 20, 20), GTextOverflowModeWordWrap, GTextAlignmentRight, NULL); - graphics_draw_text(ctx, "3", fonts_get_system_font(FONT_KEY_GOTHIC_24_BOLD), GRect(140, 74, 20, 20), GTextOverflowModeWordWrap, GTextAlignmentRight, NULL); - graphics_draw_text(ctx, "4", fonts_get_system_font(FONT_KEY_GOTHIC_24_BOLD), GRect(130, 106, 20, 20), GTextOverflowModeWordWrap, GTextAlignmentRight, NULL); - graphics_draw_text(ctx, "5", fonts_get_system_font(FONT_KEY_GOTHIC_24_BOLD), GRect(107, 126, 20, 20), GTextOverflowModeWordWrap, GTextAlignmentRight, NULL); - graphics_draw_text(ctx, "6", fonts_get_system_font(FONT_KEY_GOTHIC_24_BOLD), GRect(81, 136, 20, 20), GTextOverflowModeWordWrap, GTextAlignmentCenter, NULL); - graphics_draw_text(ctx, "7", fonts_get_system_font(FONT_KEY_GOTHIC_24_BOLD), GRect(53, 124, 20, 20), GTextOverflowModeWordWrap, GTextAlignmentLeft, NULL); - graphics_draw_text(ctx, "8", fonts_get_system_font(FONT_KEY_GOTHIC_24_BOLD), GRect(29, 106, 20, 20), GTextOverflowModeWordWrap, GTextAlignmentLeft, NULL); - graphics_draw_text(ctx, "9", fonts_get_system_font(FONT_KEY_GOTHIC_24_BOLD), GRect(20, 74, 20, 20), GTextOverflowModeWordWrap, GTextAlignmentLeft, NULL); - graphics_draw_text(ctx, "10", fonts_get_system_font(FONT_KEY_GOTHIC_24_BOLD), GRect(28, 42, 20, 20), GTextOverflowModeWordWrap, GTextAlignmentLeft, NULL); - graphics_draw_text(ctx, "11", fonts_get_system_font(FONT_KEY_GOTHIC_24_BOLD), GRect(50, 22, 20, 20), GTextOverflowModeWordWrap, GTextAlignmentLeft, NULL); + graphics_draw_text(ctx, "12", fonts_get_system_font(FONT_KEY_GOTHIC_24_BOLD), GRect(80, 10, 20, 20), GTextOverflowModeWordWrap, GTextAlignmentCenter, NULL); + graphics_draw_text(ctx, "1", fonts_get_system_font(FONT_KEY_GOTHIC_24_BOLD), GRect(107, 20, 20, 20), GTextOverflowModeWordWrap, GTextAlignmentRight, NULL); + graphics_draw_text(ctx, "2", fonts_get_system_font(FONT_KEY_GOTHIC_24_BOLD), GRect(130, 43, 20, 20), GTextOverflowModeWordWrap, GTextAlignmentRight, NULL); + graphics_draw_text(ctx, "3", fonts_get_system_font(FONT_KEY_GOTHIC_24_BOLD), GRect(140, 74, 20, 20), GTextOverflowModeWordWrap, GTextAlignmentRight, NULL); + graphics_draw_text(ctx, "4", fonts_get_system_font(FONT_KEY_GOTHIC_24_BOLD), GRect(130, 106, 20, 20), GTextOverflowModeWordWrap, GTextAlignmentRight, NULL); + graphics_draw_text(ctx, "5", fonts_get_system_font(FONT_KEY_GOTHIC_24_BOLD), GRect(107, 126, 20, 20), GTextOverflowModeWordWrap, GTextAlignmentRight, NULL); + graphics_draw_text(ctx, "6", fonts_get_system_font(FONT_KEY_GOTHIC_24_BOLD), GRect(81, 136, 20, 20), GTextOverflowModeWordWrap, GTextAlignmentCenter, NULL); + graphics_draw_text(ctx, "7", fonts_get_system_font(FONT_KEY_GOTHIC_24_BOLD), GRect(53, 124, 20, 20), GTextOverflowModeWordWrap, GTextAlignmentLeft, NULL); + graphics_draw_text(ctx, "8", fonts_get_system_font(FONT_KEY_GOTHIC_24_BOLD), GRect(29, 106, 20, 20), GTextOverflowModeWordWrap, GTextAlignmentLeft, NULL); + graphics_draw_text(ctx, "9", fonts_get_system_font(FONT_KEY_GOTHIC_24_BOLD), GRect(20, 74, 20, 20), GTextOverflowModeWordWrap, GTextAlignmentLeft, NULL); + graphics_draw_text(ctx, "10", fonts_get_system_font(FONT_KEY_GOTHIC_24_BOLD), GRect(28, 42, 20, 20), GTextOverflowModeWordWrap, GTextAlignmentLeft, NULL); + graphics_draw_text(ctx, "11", fonts_get_system_font(FONT_KEY_GOTHIC_24_BOLD), GRect(50, 22, 20, 20), GTextOverflowModeWordWrap, GTextAlignmentLeft, NULL); #endif - } + } + + + // Hours marks + graphics_context_set_stroke_width(ctx, 3); + switch_to_shadow_ctx (ctx);{ + graphics_context_set_stroke_color(ctx, gcolor (shadow_hour_marks)); + for(int i = 0; i < 12; i++) { + int hour_angle = get_angle_for_hour(i); + GPoint p0 = gpoint_from_polar(frame, GOvalScaleModeFitCircle, DEG_TO_TRIGANGLE(hour_angle)); + GPoint p1 = gpoint_from_polar(inner_hour_frame, GOvalScaleModeFitCircle, DEG_TO_TRIGANGLE(hour_angle)); + graphics_draw_line(ctx, p0, p1); + } + }revert_to_fb_ctx (ctx); + graphics_context_set_stroke_color(ctx, gcolor_hour_marks); + for(int i = 0; i < 12; i++) { + int hour_angle = get_angle_for_hour(i); + GPoint p0 = gpoint_from_polar(frame, GOvalScaleModeFitCircle, DEG_TO_TRIGANGLE(hour_angle)); + GPoint p1 = gpoint_from_polar(inner_hour_frame, GOvalScaleModeFitCircle, DEG_TO_TRIGANGLE(hour_angle)); + graphics_draw_line(ctx, p0, p1); + } + + // Minute Marks + graphics_context_set_stroke_width(ctx, 1); + switch_to_shadow_ctx (ctx);{ + graphics_context_set_stroke_color(ctx, gcolor (shadow_minute_marks)); + for(int i = 0; i < 60; i++) { + if (i % 5) { + int minute_angle = get_angle_for_minute(i); + GPoint p0 = gpoint_from_polar(frame, GOvalScaleModeFitCircle, DEG_TO_TRIGANGLE(minute_angle)); + GPoint p1 = gpoint_from_polar(inner_minute_frame, GOvalScaleModeFitCircle, DEG_TO_TRIGANGLE(minute_angle)); + graphics_draw_line(ctx, p0, p1); + } + } + }revert_to_fb_ctx (ctx); + graphics_context_set_stroke_color(ctx, gcolor_minute_marks); + for(int i = 0; i < 60; i++) { + if (i % 5) { + int minute_angle = get_angle_for_minute(i); + GPoint p0 = gpoint_from_polar(frame, GOvalScaleModeFitCircle, DEG_TO_TRIGANGLE(minute_angle)); + GPoint p1 = gpoint_from_polar(inner_minute_frame, GOvalScaleModeFitCircle, DEG_TO_TRIGANGLE(minute_angle)); + graphics_draw_line(ctx, p0, p1); + } + } + } static void hands_update_proc(Layer *layer, GContext *ctx) { - GRect bounds = layer_get_bounds(layer); - GPoint center = grect_center_point(&bounds); - int16_t second_hand_length = bounds.size.w / 2 - 5; - int16_t second_hand_tail_length = 15; - - time_t now = time(NULL); - struct tm *t = localtime(&now); - int32_t second_angle = TRIG_MAX_ANGLE * t->tm_sec / 60; - int32_t second_angle_tail = TRIG_MAX_ANGLE * (t->tm_sec + 30) / 60; - - GPoint second_hand = { - .x = (int16_t)(sin_lookup(second_angle) * (int32_t)second_hand_length / TRIG_MAX_RATIO) + center.x, - .y = (int16_t)(-cos_lookup(second_angle) * (int32_t)second_hand_length / TRIG_MAX_RATIO) + center.y, - }; - GPoint second_hand_tail = { - .x = (int16_t)(sin_lookup(second_angle_tail) * (int32_t)second_hand_tail_length / TRIG_MAX_RATIO) + center.x, - .y = (int16_t)(-cos_lookup(second_angle_tail) * (int32_t)second_hand_tail_length / TRIG_MAX_RATIO) + center.y, - }; - - // date - if (b_show_date) { - graphics_context_set_text_color(ctx, gcolor_numbers); - int offset = !b_show_numbers * 10; + GRect bounds = layer_get_bounds(layer); + GPoint center = grect_center_point(&bounds); + int16_t second_hand_length = bounds.size.w / 2 - 5; + int16_t second_hand_tail_length = 15; + + time_t now = time(NULL); + struct tm *t = localtime(&now); + int32_t second_angle = TRIG_MAX_ANGLE * t->tm_sec / 60; + int32_t second_angle_tail = TRIG_MAX_ANGLE * (t->tm_sec + 30) / 60; + + GPoint second_hand = { + .x = (int16_t)(sin_lookup(second_angle) * (int32_t)second_hand_length / TRIG_MAX_RATIO) + center.x, + .y = (int16_t)(-cos_lookup(second_angle) * (int32_t)second_hand_length / TRIG_MAX_RATIO) + center.y, + }; + GPoint second_hand_tail = { + .x = (int16_t)(sin_lookup(second_angle_tail) * (int32_t)second_hand_tail_length / TRIG_MAX_RATIO) + center.x, + .y = (int16_t)(-cos_lookup(second_angle_tail) * (int32_t)second_hand_tail_length / TRIG_MAX_RATIO) + center.y, + }; + + // date + if (b_show_date) { + graphics_context_set_text_color(ctx, gcolor_numbers); + int offset = !b_show_numbers * 10; #ifdef PBL_RECT - graphics_draw_text(ctx, s_date_buffer, fonts_get_system_font(FONT_KEY_GOTHIC_14), GRect(80, 75, 40 + offset, 14), GTextOverflowModeWordWrap, GTextAlignmentCenter, NULL); + graphics_draw_text(ctx, s_date_buffer, fonts_get_system_font(FONT_KEY_GOTHIC_14), GRect(80, 75, 40 + offset, 14), GTextOverflowModeWordWrap, GTextAlignmentCenter, NULL); #else - graphics_draw_text(ctx, s_date_buffer, fonts_get_system_font(FONT_KEY_GOTHIC_18), GRect(100, 78, 45 + offset, 14), GTextOverflowModeWordWrap, GTextAlignmentCenter, NULL); + graphics_draw_text(ctx, s_date_buffer, fonts_get_system_font(FONT_KEY_GOTHIC_18), GRect(100, 78, 45 + offset, 14), GTextOverflowModeWordWrap, GTextAlignmentCenter, NULL); #endif - } + } - // temperature - if (b_show_temperature) { - graphics_context_set_text_color(ctx, gcolor_numbers); - int offset = !b_show_numbers * 10; + // temperature + if (b_show_temperature) { + graphics_context_set_text_color(ctx, gcolor_numbers); + int offset = !b_show_numbers * 10; #ifdef PBL_RECT - graphics_draw_text(ctx, s_temp_buffer, fonts_get_system_font(FONT_KEY_GOTHIC_14), GRect(27 - offset, 75, 40 + offset, 14), GTextOverflowModeWordWrap, GTextAlignmentCenter, NULL); + graphics_draw_text(ctx, s_temp_buffer, fonts_get_system_font(FONT_KEY_GOTHIC_14), GRect(27 - offset, 75, 40 + offset, 14), GTextOverflowModeWordWrap, GTextAlignmentCenter, NULL); #else - graphics_draw_text(ctx, s_temp_buffer, fonts_get_system_font(FONT_KEY_GOTHIC_18), GRect(40 - offset, 78, 40 + offset, 14), GTextOverflowModeWordWrap, GTextAlignmentCenter, NULL); + graphics_draw_text(ctx, s_temp_buffer, fonts_get_system_font(FONT_KEY_GOTHIC_18), GRect(40 - offset, 78, 40 + offset, 14), GTextOverflowModeWordWrap, GTextAlignmentCenter, NULL); #endif - } - - // minute hand - graphics_context_set_fill_color(ctx, gcolor_minute_hand); - gpath_rotate_to(s_minute_arrow, TRIG_MAX_ANGLE * t->tm_min / 60); - gpath_draw_filled(ctx, s_minute_arrow); - - // hour hand - graphics_context_set_fill_color(ctx, gcolor_hour_hand); - gpath_rotate_to(s_hour_arrow, (TRIG_MAX_ANGLE * (((t->tm_hour % 12) * 6) + (t->tm_min / 10))) / (12 * 6)); - gpath_draw_filled(ctx, s_hour_arrow); - - // second hand - if (b_show_second_hand) { - graphics_context_set_stroke_color(ctx, gcolor_second_hand); - graphics_draw_line(ctx, second_hand, center); - graphics_draw_line(ctx, second_hand_tail, center); - } - - // dot in the middle - graphics_context_set_fill_color(ctx, gcolor_second_hand); - graphics_fill_circle(ctx, GPoint(bounds.size.w / 2, bounds.size.h / 2), 4); + } + + // minute hand + gpath_rotate_to(s_minute_arrow, TRIG_MAX_ANGLE * t->tm_min / 60); + switch_to_shadow_ctx (ctx);{ + graphics_context_set_fill_color(ctx, gcolor (shadow_minute_hand)); + gpath_draw_filled(ctx, s_minute_arrow); + }revert_to_fb_ctx (ctx); + graphics_context_set_fill_color(ctx, gcolor_minute_hand); + gpath_draw_filled(ctx, s_minute_arrow); + + // hour hand + gpath_rotate_to(s_hour_arrow, (TRIG_MAX_ANGLE * (((t->tm_hour % 12) * 6) + (t->tm_min / 10))) / (12 * 6)); + switch_to_shadow_ctx (ctx);{ + graphics_context_set_fill_color(ctx, gcolor (shadow_hour_hand)); + gpath_draw_filled(ctx, s_hour_arrow); + }revert_to_fb_ctx (ctx); + graphics_context_set_fill_color(ctx, gcolor_hour_hand); + gpath_draw_filled(ctx, s_hour_arrow); + + if (b_show_second_hand) { + switch_to_shadow_ctx (ctx);{ + graphics_context_set_fill_color(ctx, gcolor (shadow_second_hand)); + graphics_draw_line(ctx, second_hand, center); + graphics_draw_line(ctx, second_hand_tail, center); + }revert_to_fb_ctx (ctx); + graphics_context_set_stroke_color(ctx, gcolor_second_hand); + graphics_draw_line(ctx, second_hand, center); + graphics_draw_line(ctx, second_hand_tail, center); + } + + switch_to_shadow_ctx (ctx);{ + graphics_context_set_fill_color(ctx, gcolor (shadow_dot)); + graphics_fill_circle(ctx, GPoint(bounds.size.w / 2, bounds.size.h / 2), 4); + }revert_to_fb_ctx (ctx); + graphics_context_set_fill_color(ctx, gcolor_second_hand); + graphics_fill_circle(ctx, GPoint(bounds.size.w / 2, bounds.size.h / 2), 4); + + create_shadow (ctx, NW); + reset_shadow (); } static void date_update_proc(Layer *layer, GContext *ctx) { - time_t now = time(NULL); - struct tm *t = localtime(&now); + time_t now = time(NULL); + struct tm *t = localtime(&now); - strftime(s_date_buffer, sizeof(s_date_buffer), "%a %d", t); - uppercase(s_date_buffer); + strftime(s_date_buffer, sizeof(s_date_buffer), "%a %d", t); + uppercase(s_date_buffer); } static void handle_second_tick(struct tm *tick_time, TimeUnits units_changed) { - layer_mark_dirty(window_get_root_layer(window)); + layer_mark_dirty(window_get_root_layer(window)); } static void window_load(Window *window) { - Layer *window_layer = window_get_root_layer(window); - GRect bounds = layer_get_bounds(window_layer); + Layer *window_layer = window_get_root_layer(window); + GRect bounds = layer_get_bounds(window_layer); + + shadow_hour_marks = new_shadowing_object (1,0); + shadow_minute_marks = new_shadowing_object (1, 0); + shadow_numbers = new_shadowing_object (1, 0); - s_simple_bg_layer = layer_create(bounds); - layer_set_update_proc(s_simple_bg_layer, bg_update_proc); - layer_add_child(window_layer, s_simple_bg_layer); + shadow_minute_hand = new_shadowing_object (2, 2); + shadow_hour_hand = new_shadowing_object (2, 4); + shadow_second_hand = new_shadowing_object (1, 4); + shadow_dot = new_shadowing_object (-1, 4); - window_set_background_color(window, gcolor_background); + s_simple_bg_layer = layer_create(bounds); + layer_set_update_proc(s_simple_bg_layer, bg_update_proc); + layer_add_child(window_layer, s_simple_bg_layer); - s_date_layer = layer_create(bounds); - layer_set_update_proc(s_date_layer, date_update_proc); - layer_add_child(window_layer, s_date_layer); + window_set_background_color(window, gcolor_background); - s_hands_layer = layer_create(bounds); - layer_set_update_proc(s_hands_layer, hands_update_proc); - layer_add_child(window_layer, s_hands_layer); + s_date_layer = layer_create(bounds); + layer_set_update_proc(s_date_layer, date_update_proc); + layer_add_child(window_layer, s_date_layer); + + s_hands_layer = layer_create(bounds); + layer_set_update_proc(s_hands_layer, hands_update_proc); + layer_add_child(window_layer, s_hands_layer); + + load_persisted_values(); - load_persisted_values(); } static void window_unload(Window *window) { - layer_destroy(s_simple_bg_layer); - layer_destroy(s_date_layer); + layer_destroy(s_simple_bg_layer); + layer_destroy(s_date_layer); + + text_layer_destroy(s_day_label); + text_layer_destroy(s_num_label); - text_layer_destroy(s_day_label); - text_layer_destroy(s_num_label); + layer_destroy(s_hands_layer); - layer_destroy(s_hands_layer); + destroy_shadow_ctx (); } -static void init() { - - // Default colors - gcolor_background = GColorBlack; - gcolor_minute_hand = GColorWhite; - - #ifdef PBL_COLOR - gcolor_hour_marks = GColorLightGray; - gcolor_minute_marks = GColorDarkGray; - gcolor_numbers = GColorLightGray; - gcolor_hour_hand = GColorRed; - gcolor_second_hand = GColorRed; - #else - gcolor_hour_marks = GColorWhite; - gcolor_minute_marks = GColorWhite; - gcolor_numbers = GColorWhite; - gcolor_hour_hand = GColorWhite; - gcolor_second_hand = GColorWhite; - #endif - - b_show_numbers = true; - b_show_second_hand = true; - b_show_date = true; - b_show_temperature = true; - - window = window_create(); - window_set_window_handlers(window, (WindowHandlers) { - .load = window_load, - .unload = window_unload, - }); - window_stack_push(window, true); - - s_temp_buffer[0] = '\0'; - s_date_buffer[0] = '\0'; - - // init hand paths - s_minute_arrow = gpath_create(&MINUTE_HAND_POINTS); - s_hour_arrow = gpath_create(&HOUR_HAND_POINTS); - - Layer *window_layer = window_get_root_layer(window); - GRect bounds = layer_get_bounds(window_layer); - GPoint center = grect_center_point(&bounds); - gpath_move_to(s_minute_arrow, center); - gpath_move_to(s_hour_arrow, center); - - tick_timer_service_subscribe(SECOND_UNIT, handle_second_tick); - - app_message_register_inbox_received(inbox_received_handler); - app_message_open(64, 64); +static void init() { + + // Default colors + gcolor_background = GColorOxfordBlue; + gcolor_minute_hand = GColorChromeYellow; + +#ifdef PBL_COLOR + gcolor_hour_marks = GColorWhite; + gcolor_minute_marks = GColorWhite; + gcolor_numbers = GColorChromeYellow; + gcolor_hour_hand = GColorWhite; + gcolor_second_hand = GColorChromeYellow; +#else + gcolor_hour_marks = GColorWhite; + gcolor_minute_marks = GColorWhite; + gcolor_numbers = GColorWhite; + gcolor_hour_hand = GColorWhite; + gcolor_second_hand = GColorWhite; +#endif + + b_show_numbers = true; + b_show_second_hand = true; + b_show_date = true; + b_show_temperature = true; + + window = window_create(); + window_set_window_handlers(window, (WindowHandlers) { + .load = window_load, + .unload = window_unload, + }); + window_stack_push(window, true); + + s_temp_buffer[0] = '\0'; + s_date_buffer[0] = '\0'; + + // init hand paths + s_minute_arrow = gpath_create(&MINUTE_HAND_POINTS); + s_hour_arrow = gpath_create(&HOUR_HAND_POINTS); + + Layer *window_layer = window_get_root_layer(window); + GRect bounds = layer_get_bounds(window_layer); + GPoint center = grect_center_point(&bounds); + gpath_move_to(s_minute_arrow, center); + gpath_move_to(s_hour_arrow, center); + + tick_timer_service_subscribe(SECOND_UNIT, handle_second_tick); + + app_message_register_inbox_received(inbox_received_handler); + app_message_open(64, 64); } static void deinit() { - gpath_destroy(s_minute_arrow); - gpath_destroy(s_hour_arrow); + gpath_destroy(s_minute_arrow); + gpath_destroy(s_hour_arrow); - tick_timer_service_unsubscribe(); - window_destroy(window); + tick_timer_service_unsubscribe(); + window_destroy(window); } int main() { - init(); - app_event_loop(); - deinit(); + init(); + app_event_loop(); + deinit(); } char *uppercase(char *str) { - for (int i = 0; str[i] != 0; i++) { - if (str[i] >= 'a' && str[i] <= 'z') { - str[i] -= 0x20; - } + for (int i = 0; str[i] != 0; i++) { + if (str[i] >= 'a' && str[i] <= 'z') { + str[i] -= 0x20; } + } - return str; + return str; } diff --git a/src/libshadow.c b/src/libshadow.c new file mode 100644 index 0000000..21aeada --- /dev/null +++ b/src/libshadow.c @@ -0,0 +1,280 @@ +/* Copyright (C): Baptiste Fouques 2016 */ + +/* This file is part of Shadow Library. */ + +/* Shadow Library 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 3 of the License, or */ +/* (at your option) any later version. */ + +/* Foobar 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 LesserGeneral Public License for more details. */ + +/* You should have received a copy of the GNU Lesser General Public License */ +/* along with Shadow Library. If not, see . */ + +#include + +#include "libshadow.h" + +void set_fb_pixel(GBitmap *bitmap, int y, int x, GColor color); +GColor get_fb_pixel(GBitmap *bitmap, int y, int x); + +GColor get_light_shadow_color (GColor c); +GColor get_light_bright_color (GColor c); + +//////////////////////////////////////////////////////////////////////////////// + +typedef struct { + int inner_z, outer_z; +} GShadow_Information; +static GShadow_Information shadow_object_list [GShadowMaxRef]; +static GShadow shadow_object_current = 0; + +static GBitmap *shadow_bitmap = NULL; +static uint8_t *shadow_bitmap_data; +static size_t shadow_bitmap_size; +static GRect shadow_bitmap_bounds; +static uint16_t shadow_bitmap_bytes_per_row; +static GBitmapFormat shadow_bitmap_format; + +static uint8_t *fb_data; + +GColor8 gcolor (GShadow shadow) { + return (GColor8) {.argb = (uint8_t) shadow}; +} + +GShadow new_shadowing_object (int inner_z, int outer_z) { + GShadow r = shadow_object_current; + shadow_object_list [shadow_object_current] = + (GShadow_Information) { .inner_z = inner_z, + .outer_z = outer_z}; + shadow_object_current = (shadow_object_current + 1) % GShadowMaxRef; + + return GShadowUnclear | r; +} + +void reset_shadow () { + memset (shadow_bitmap_data, GShadowClear, shadow_bitmap_size); +} + +void switch_to_shadow_ctx (GContext *ctx) { + GBitmap *fb = graphics_capture_frame_buffer(ctx); { + if (shadow_bitmap == NULL) { + shadow_bitmap_format = gbitmap_get_format (fb); + shadow_bitmap_bounds = gbitmap_get_bounds (fb); + shadow_bitmap_bytes_per_row = gbitmap_get_bytes_per_row (fb); + shadow_bitmap_size = gbitmap_get_bytes_per_row(fb) * gbitmap_get_bounds(fb).size.h; + + shadow_bitmap_data = malloc (shadow_bitmap_size); + memset (shadow_bitmap_data, GShadowClear, shadow_bitmap_size); + + shadow_bitmap = gbitmap_create_with_data (shadow_bitmap_data); + gbitmap_set_data (shadow_bitmap, shadow_bitmap_data, shadow_bitmap_format, shadow_bitmap_bytes_per_row,true); + gbitmap_set_bounds (shadow_bitmap, shadow_bitmap_bounds); + } + + fb_data = gbitmap_get_data (fb); + gbitmap_set_data (fb, shadow_bitmap_data, shadow_bitmap_format, shadow_bitmap_bytes_per_row, true); + + } graphics_release_frame_buffer(ctx, fb); +} + +void revert_to_fb_ctx (GContext *ctx) { + GBitmap *fb = graphics_capture_frame_buffer(ctx); { + gbitmap_set_data (fb, fb_data, shadow_bitmap_format, shadow_bitmap_bytes_per_row, true); + } graphics_release_frame_buffer(ctx, fb); +} + +void destroy_shadow_ctx () { + gbitmap_destroy (shadow_bitmap); +}; + +void create_shadow (GContext *ctx, int32_t angle) { + // compute x and y offset from angle and height (z) + const int offset_x = (- cos_lookup (angle) * GShadowMaxValue * 2) / TRIG_MAX_RATIO; + const int offset_y = (sin_lookup (angle) * GShadowMaxValue * 2) / TRIG_MAX_RATIO; + + GBitmap *fb = graphics_capture_frame_buffer(ctx); + { + // Manipulate the image data... + const GRect bounds = gbitmap_get_bounds(fb); + // Iterate over all rows + for(int y = bounds.origin.y; y < bounds.origin.y + bounds.size.h; y++) { + for(int x = bounds.origin.x; x < bounds.origin.x + bounds.size.w; x++) { + const GShadow id = (GShadow)get_fb_pixel (shadow_bitmap, y, x).argb; + if (id != GShadowClear) { + const GShadow inner_z = shadow_object_list [id & GShadowMaxRef].inner_z; + const GShadow outer_z = shadow_object_list [id & GShadowMaxRef].outer_z; + if (inner_z) { + const int inner_x_plus = x + (offset_x * inner_z) / GShadowMaxValue; + const int inner_y_plus = y + (offset_y * inner_z) / GShadowMaxValue; + const int inner_x_minus = x - (offset_x * inner_z) / GShadowMaxValue; + const int inner_y_minus = y - (offset_y * inner_z) / GShadowMaxValue; + + if (bounds.origin.y <= inner_y_plus && inner_y_plus < bounds.origin.y + bounds.size.h && + bounds.origin.x <= inner_x_plus && inner_x_plus < bounds.origin.x + bounds.size.w && + bounds.origin.y <= inner_y_minus && inner_y_minus < bounds.origin.y + bounds.size.h && + bounds.origin.x <= inner_x_minus && inner_x_minus < bounds.origin.x + bounds.size.w) { + const int dec_id_plus = (GShadow) get_fb_pixel (shadow_bitmap, inner_y_plus, inner_x_plus).argb; + const int dec_id_minus = (GShadow) get_fb_pixel (shadow_bitmap, inner_y_minus, inner_x_minus).argb; + // we are still on the same object, then shadow apply + if (id == dec_id_minus && id == dec_id_plus) { + // we are in the middle of the object + } else if (id == dec_id_minus && id != dec_id_plus) { + // we are at the shadow side of the object + set_fb_pixel (fb, y, x, get_light_shadow_color (get_fb_pixel (fb, y, x))); + } else if (id != dec_id_minus && id == dec_id_plus) { + // we are at the bright side of the object + set_fb_pixel (fb, y, x, get_light_bright_color (get_fb_pixel (fb, y, x))); + } else { + // we are at an edge of the object + } + } + } + if (outer_z) { + const int outer_x = x + (offset_x * outer_z) / GShadowMaxValue; + const int outer_y = y + (offset_y * outer_z) / GShadowMaxValue; + if (bounds.origin.y <= outer_y && outer_y < bounds.origin.y + bounds.size.h && + bounds.origin.x <= outer_x && outer_x < bounds.origin.x + bounds.size.w ) { + const GShadow dec_id_plus = (GShadow) get_fb_pixel (shadow_bitmap, outer_y, outer_x).argb; + const int dec_z = (dec_id_plus != GShadowClear)? shadow_object_list [dec_id_plus].outer_z : 0; + if (id != dec_id_plus && + (outer_z == GShadowClear || outer_z > dec_z)) { + // we are down the object, then shadowing occurs + set_fb_pixel (fb, outer_y, outer_x, get_light_shadow_color (get_fb_pixel (fb, outer_y, outer_x))); + } + } + } + } + } + } + } graphics_release_frame_buffer(ctx, fb); +} + +//////////////////////////////////////////////////////////////////////////////// + + +// get pixel color at given coordinates +GColor get_fb_pixel(GBitmap *bitmap, int y, int x) { + static uint16_t byte_per_row; + static bool first_run = true; + const uint8_t *data = gbitmap_get_data (bitmap); + + if (first_run) { + byte_per_row = gbitmap_get_bytes_per_row (bitmap); + first_run = false; + } + + return (GColor)data[y*byte_per_row + x]; +} + +// set pixel color at given coordinates +void set_fb_pixel(GBitmap *bitmap, int y, int x, GColor color) { + static uint16_t byte_per_row; + static bool first_run = true; + uint8_t *data = gbitmap_get_data (bitmap); + + if (first_run) { + byte_per_row = gbitmap_get_bytes_per_row (bitmap); + first_run = false; + } + + ((GColor *)data)[y*byte_per_row + x] = color; +} + +GColor color_matrix [64][2] += { + /* GColorBlack ((uint8_t)0b11000000)y */ {GColorBlack, GColorDarkGray}, + /* GColorOxfordBlue ((uint8_t)0b11000001)y */ {GColorBlack, GColorDukeBlue}, + /* GColorDukeBlue ((uint8_t)0b11000010)y */ {GColorOxfordBlue, GColorBlue}, + /* GColorBlue ((uint8_t)0b11000011)y */ {GColorDukeBlue, GColorBlueMoon}, + /* GColorDarkGreen ((uint8_t)0b11000100)y */ {GColorBlack, GColorMayGreen}, + /* GColorMidnightGreen ((uint8_t)0b11000101)y */ {GColorOxfordBlue, GColorCadetBlue}, + /* GColorCobaltBlue ((uint8_t)0b11000110)y */ {GColorDukeBlue, GColorVividCerulean}, + /* GColorBlueMoon ((uint8_t)0b11000111)y */ {GColorBlue, GColorPictonBlue}, + /* GColorIslamicGreen ((uint8_t)0b11001000)y */ {GColorDarkGreen, GColorGreen}, + /* GColorJaegerGreen ((uint8_t)0b11001001)y */ {GColorDarkGreen, GColorMalachite}, + /* GColorTiffanyBlue ((uint8_t)0b11001010)y */ {GColorMidnightGreen, GColorMediumSpringGreen}, + /* GColorVividCerulean ((uint8_t)0b11001011)y */ {GColorCobaltBlue, GColorCeleste}, + /* GColorGreen ((uint8_t)0b11001100)y */ {GColorIslamicGreen, GColorInchworm}, + /* GColorMalachite ((uint8_t)0b11001101)y */ {GColorJaegerGreen, GColorMintGreen}, + /* GColorMediumSpringGreen ((uint8_t)0b11001110)y */ {GColorTiffanyBlue, GColorCeleste}, + /* GColorCyan ((uint8_t)0b11001111)y */ {GColorBlue, GColorCeleste}, + /* GColorBulgarianRose ((uint8_t)0b11010000)y */ {GColorBlack, GColorDarkCandyAppleRed}, + /* GColorImperialPurple ((uint8_t)0b11010001)y */ {GColorBlack, GColorPurple}, + /* GColorIndigo ((uint8_t)0b11010010)y */ {GColorOxfordBlue, GColorVividViolet}, + /* GColorElectricUltramarine ((uint8_t)0b11010011)y */ {GColorOxfordBlue, GColorBabyBlueEyes}, + /* GColorArmyGreen ((uint8_t)0b11010100)y */ {GColorBlack, GColorBrass}, + /* GColorDarkGray ((uint8_t)0b11010101)y */ {GColorBlack, GColorLightGray}, + /* GColorLiberty ((uint8_t)0b11010110)y */ {GColorOxfordBlue, GColorBabyBlueEyes}, + /* GColorVeryLightBlue ((uint8_t)0b11010111)y */ {GColorDukeBlue, GColorBabyBlueEyes}, + /* GColorKellyGreen ((uint8_t)0b11011000)y */ {GColorDarkGreen, GColorSpringBud}, + /* GColorMayGreen ((uint8_t)0b11011001)y */ {GColorMidnightGreen, GColorMalachite}, + /* GColorCadetBlue ((uint8_t)0b11011010)y */ {GColorMidnightGreen, GColorMediumSpringGreen}, + /* GColorPictonBlue ((uint8_t)0b11011011)y */ {GColorCobaltBlue, GColorCeleste}, + /* GColorBrightGreen ((uint8_t)0b11011100)y */ {GColorKellyGreen, GColorMintGreen}, + /* GColorScreaminGreen ((uint8_t)0b11011101)y */ {GColorGreen, GColorMintGreen}, + /* GColorMediumAquamarine ((uint8_t)0b11011110)y */ {GColorJaegerGreen, GColorCeleste}, + /* GColorElectricBlue ((uint8_t)0b11011111)y */ {GColorTiffanyBlue, GColorCeleste}, + /* GColorDarkCandyAppleRed ((uint8_t)0b11100000)y */ {GColorBulgarianRose, GColorSunsetOrange}, + /* GColorJazzberryJam ((uint8_t)0b11100001)y */ {GColorImperialPurple, GColorMagenta}, + /* GColorPurple ((uint8_t)0b11100010)y */ {GColorImperialPurple, GColorShockingPink}, + /* GColorVividViolet ((uint8_t)0b11100011)y */ {GColorImperialPurple, GColorBabyBlueEyes}, + /* GColorWindsorTan ((uint8_t)0b11100100)y */ {GColorBlack, GColorRajah}, + /* GColorRoseVale ((uint8_t)0b11100101)y */ {GColorBulgarianRose, GColorMelon}, + /* GColorPurpureus ((uint8_t)0b11100110)y */ {GColorPurple, GColorRichBrilliantLavender}, + /* GColorLavenderIndigo ((uint8_t)0b11100111)y */ {GColorPurple, GColorRichBrilliantLavender}, + /* GColorLimerick ((uint8_t)0b11101000)y */ {GColorArmyGreen, GColorSpringBud}, + /* GColorBrass ((uint8_t)0b11101001)y */ {GColorArmyGreen, GColorSpringBud}, + /* GColorLightGray ((uint8_t)0b11101010)y */ {GColorDarkGray, GColorWhite}, + /* GColorBabyBlueEyes ((uint8_t)0b11101011)y */ {GColorElectricUltramarine, GColorWhite}, + /* GColorSpringBud ((uint8_t)0b11101100)y */ {GColorKellyGreen, GColorWhite}, + /* GColorInchworm ((uint8_t)0b11101101)y */ {GColorSpringBud, GColorWhite}, + /* GColorMintGreen ((uint8_t)0b11101110)y */ {GColorScreaminGreen, GColorWhite}, + /* GColorCeleste ((uint8_t)0b11101111)y */ {GColorElectricBlue, GColorWhite}, + /* GColorRed ((uint8_t)0b11110000)y */ {GColorDarkCandyAppleRed, GColorSunsetOrange}, + /* GColorFolly ((uint8_t)0b11110001)y */ {GColorRoseVale, GColorBrilliantRose}, + /* GColorFashionMagenta ((uint8_t)0b11110010)y */ {GColorJazzberryJam, GColorBrilliantRose}, + /* GColorMagenta ((uint8_t)0b11110011)y */ {GColorJazzberryJam, GColorRichBrilliantLavender}, + /* GColorOrange ((uint8_t)0b11110100)y */ {GColorWindsorTan, GColorRajah}, + /* GColorSunsetOrange ((uint8_t)0b11110101)y */ {GColorRed, GColorMelon}, + /* GColorBrilliantRose ((uint8_t)0b11110110)y */ {GColorFashionMagenta, GColorRichBrilliantLavender}, + /* GColorShockingPink ((uint8_t)0b11110111)y */ {GColorJazzberryJam, GColorRichBrilliantLavender}, + /* GColorChromeYellow ((uint8_t)0b11111000)y */ {GColorWindsorTan, GColorYellow}, + /* GColorRajah ((uint8_t)0b11111001)y */ {GColorChromeYellow, GColorIcterine}, + /* GColorMelon ((uint8_t)0b11111010)y */ {GColorSunsetOrange, GColorWhite}, + /* GColorRichBrilliantLavender ((uint8_t)0b11111011)y */ {GColorMagenta, GColorWhite}, + /* GColorYellow ((uint8_t)0b11111100)y */ {GColorChromeYellow, GColorYellow}, + /* GColorIcterine ((uint8_t)0b11111101)y */ {GColorYellow, GColorPastelYellow}, + /* GColorPastelYellow ((uint8_t)0b11111110)y */ {GColorIcterine, GColorWhite}, + /* GColorWhite ((uint8_t)0b11111111)y */ {GColorLightGray, GColorWhite} +}; + +inline GColor get_light_shadow_color (GColor c) { + return color_matrix [c.argb & 0b00111111][0]; +} + +GColor get_light_bright_color (GColor c) { + return color_matrix [c.argb & 0b00111111][1]; +} + +void test_shadow_layer_proc (Layer *layer, GContext *ctx) { + GRect bounds = layer_get_bounds(layer); + + for (int i = 0; i < 64; i++) { + int x = i % 4; int y = i / 4; + int w = bounds.size.w / 4; int h = bounds.size.h / (64 / 4); + GColor c = (GColor){.argb = (0b11<<6)+i}; + GColor r = get_light_shadow_color (c); + GColor s = get_light_bright_color (c); + graphics_context_set_fill_color(ctx, r); + graphics_fill_rect (ctx, GRect (x * w, y * h, w / 3, h), 0, GCornerNone); + graphics_context_set_fill_color(ctx, c); + graphics_fill_rect (ctx, GRect (x * w + w / 3, y * h, w / 3, h), 0, GCornerNone); + graphics_context_set_fill_color(ctx, s); + graphics_fill_rect (ctx, GRect (x * w + 2 * w / 3, y * h, w / 3, h), 0, GCornerNone); + } +} diff --git a/src/libshadow.h b/src/libshadow.h new file mode 100644 index 0000000..7255268 --- /dev/null +++ b/src/libshadow.h @@ -0,0 +1,42 @@ +/* Copyright (C): Baptiste Fouques 2016 */ + +/* This file is part of Shadow Library. */ + +/* Shadow Library 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 3 of the License, or */ +/* (at your option) any later version. */ + +/* Foobar 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 LesserGeneral Public License for more details. */ + +/* You should have received a copy of the GNU Lesser General Public License */ +/* along with Shadow Library. If not, see . */ + +#pragma once + +#include +struct ShadowBitmap; +typedef struct ShadowBitmap ShadowBitmap; + +#define NW (((TRIG_MAX_ANGLE) * 3) / 8) + +typedef int8_t GShadow; +#define GShadowClear ((GShadow) 0b00000000) +#define GShadowMaxRef ((GShadow) 0b00111111) +#define GShadowUnclear (~ GShadowMaxRef) +#define GShadowMaxValue 10000 +GColor gcolor (GShadow shadow); + +GShadow new_shadowing_object (int inner_z, int outer_z); + +void switch_to_shadow_ctx (GContext *ctx); +void revert_to_fb_ctx (GContext *ctx); +void destroy_shadow_ctx (); +// The angle value is scaled linearly, such that a value of 0x10000 corresponds to 360 degrees or 2 PI radians. +void create_shadow (GContext *ctx, int32_t angle); +void reset_shadow (); + +void test_shadow_layer_proc (Layer *layer, GContext *ctx);