// Circular graph layer update procedure void graph_layer_update_proc(Layer *my_layer, GContext* ctx) { // Fill the path: graphics_context_set_fill_color(ctx, GColorBlack); if (visitors > 0) { graphics_draw_arc(ctx, GPoint(62, 60), 60, 5, 0, (((double)visitors / max_visitors) * 360)); } graphics_draw_arc(ctx, GPoint(62, 60), 60, 1, 0, 360); }
void draw_hand_layer(Layer* l, GContext* ctx) { GColor foreground_color = gcolor_legible_over(s_background_color); GRect bounds = layer_get_frame(l); GPoint center = GPoint(bounds.size.w / 2, bounds.size.h / 2); graphics_context_set_antialiased(ctx, true); graphics_context_set_stroke_color(ctx, foreground_color); graphics_context_set_fill_color(ctx, foreground_color); graphics_context_set_stroke_width(ctx, 3); time_t ts = time(NULL); struct tm* now = localtime(&ts); GRect reduced_bounds = bounds; int arc_offset = PBL_IF_ROUND_ELSE(24, 18); reduced_bounds.origin.x += arc_offset; reduced_bounds.origin.y += arc_offset; reduced_bounds.size.w -= (arc_offset << 1); reduced_bounds.size.h -= (arc_offset << 1); // initially, angle is relative to top (wrong) int angle = TRIG_MAX_ANGLE * (now->tm_hour * 60 + now->tm_min) / 1440; // make 0 at the bottom angle = (angle + TRIG_MAX_ANGLE / 2) % TRIG_MAX_ANGLE; graphics_context_set_fill_color(ctx, s_complementary_color); int hand_length = MIN(reduced_bounds.size.h, reduced_bounds.size.w) / 2; int radial_inset = ((hand_length - 20) * inset_pct) / 100; if (angle < TRIG_MAX_ANGLE / 2) { // first draw the bottom half graphics_fill_radial(ctx, reduced_bounds, GOvalScaleModeFitCircle, radial_inset, TRIG_MAX_ANGLE / 2, TRIG_MAX_ANGLE); graphics_draw_arc(ctx, reduced_bounds, GOvalScaleModeFitCircle, TRIG_MAX_ANGLE / 2, TRIG_MAX_ANGLE); // then the rest graphics_fill_radial(ctx, reduced_bounds, GOvalScaleModeFitCircle, radial_inset, 0, angle); graphics_draw_arc(ctx, reduced_bounds, GOvalScaleModeFitCircle, 0, angle); } else { graphics_fill_radial(ctx, reduced_bounds, GOvalScaleModeFitCircle, radial_inset, TRIG_MAX_ANGLE / 2, angle); graphics_draw_arc(ctx, reduced_bounds, GOvalScaleModeFitCircle, TRIG_MAX_ANGLE / 2, angle); } graphics_context_set_stroke_width(ctx, 2); GPoint hand_end; hand_end.y = (-cos_lookup(angle) * hand_length / TRIG_MAX_RATIO) + center.y; hand_end.x = (sin_lookup(angle) * hand_length / TRIG_MAX_RATIO) + center.x; graphics_draw_line(ctx, center, hand_end); GPoint sm_end = GPoint(center.x, center.y + hand_length); GPoint sm_start = GPoint(center.x, sm_end.y - radial_inset); graphics_draw_line(ctx, sm_start, sm_end); }
static void updateScreen(Layer *layer, GContext *ctx) { graphics_context_set_fill_color(ctx, GColorWhite); graphics_fill_circle(ctx, center, outerCircleOuterRadius); graphics_context_set_fill_color(ctx, GColorBlack); graphics_fill_circle(ctx, center, outerCircleInnerRadius); graphics_draw_arc(ctx, center, outerCircleOuterRadius+1, OUTER_CIRCLE_THICKNESS+2, min_a1, min_a2, GColorBlack); graphics_draw_arc(ctx, center, innerCircleOuterRadius, INNER_CIRCLE_THICKNESS, hour_a1, hour_a2, GColorWhite); }
void bipercent_draw_circle(Layer *layer, GContext *ctx) { BipercentLayerData *data = (BipercentLayerData*) layer_get_data(layer); int end_angle = data->percent * 360 / 100; GRect rect = layer_get_bounds(layer); graphics_fill_radial(ctx, rect, GOvalScaleModeFitCircle, RADIAL_R, DEG_TO_TRIGANGLE(0), DEG_TO_TRIGANGLE(end_angle)); graphics_draw_arc(ctx, rect, GOvalScaleModeFitCircle, DEG_TO_TRIGANGLE(end_angle), DEG_TO_TRIGANGLE(360)); graphics_draw_arc(ctx, grect_inset(layer_get_bounds(layer), GEdgeInsets(RADIAL_R)) , GOvalScaleModeFitCircle, DEG_TO_TRIGANGLE(end_angle), DEG_TO_TRIGANGLE(360)); }
void month_display_layer_update_callback(Layer *me, GContext* ctx) { (void)me; PblTm t; get_time(&t); unsigned int angle = (t.tm_mon + 1) * 15; GPoint center = grect_center_point(&me->frame); center.y += 10; graphics_context_set_fill_color(ctx, GColorWhite); graphics_draw_arc(ctx, center, 42, 20, 0, angle); //graphics_draw_line(ctx, GPoint(7, center.y), GPoint(20, center.y)); //graphics_draw_line(ctx, GPoint(124, center.y), GPoint(137, center.y)); for (int x = 0; x < 2; x++) for (int y = 0; y < 2; y++) { graphics_draw_pixel(ctx, GPoint(center.x - 01 + x, center.y + 18 + y)); graphics_draw_pixel(ctx, GPoint(center.x - 13 + x, center.y + 13 + y)); graphics_draw_pixel(ctx, GPoint(center.x + 13 + x, center.y + 13 + y)); } }
// Layer representing the pet pebble void draw_pet_pebble(Layer *layer, GContext *ctx) { PetPebbleState pet_state = current_pet_state(); GPoint BODY_CENTER = GPoint(90, 120); int EYES_HEIGHT = 115; int EYE_LEFT_CENTER = 80; int EYE_RIGHT_CENTER = 100; uint16_t radius = 30; // Draw the pet pebble body graphics_context_set_stroke_color(ctx, GColorCobaltBlue); graphics_context_set_fill_color(ctx, GColorCyan); graphics_context_set_stroke_width(ctx, 5); graphics_draw_circle(ctx, BODY_CENTER, radius); graphics_fill_circle(ctx, BODY_CENTER, radius); // Draw the pet pebble eyes graphics_context_set_stroke_color(ctx, GColorBlack); graphics_context_set_fill_color(ctx, GColorBlack); graphics_context_set_stroke_width(ctx, 2); radius = 2; if (pet_state == SLEEPING) { graphics_draw_line(ctx, GPoint(EYE_LEFT_CENTER-5, EYES_HEIGHT), GPoint(EYE_LEFT_CENTER+5, EYES_HEIGHT)); graphics_draw_line(ctx, GPoint(EYE_RIGHT_CENTER-5, EYES_HEIGHT), GPoint(EYE_RIGHT_CENTER+5, EYES_HEIGHT)); } else { graphics_draw_circle( ctx, GPoint(EYE_LEFT_CENTER, EYES_HEIGHT),radius); graphics_draw_circle( ctx, GPoint(EYE_RIGHT_CENTER, EYES_HEIGHT), radius); } // Draw the pet pebble mouth if (pet_state == SLEEPING) { graphics_draw_circle(ctx, GPoint((EYE_LEFT_CENTER+EYE_RIGHT_CENTER)/2, EYES_HEIGHT+13), 5); // Draw "Zzzz" to show that the pet pebble is asleep graphics_draw_text(ctx, "Zzzz", fonts_get_system_font(FONT_KEY_ROBOTO_CONDENSED_21), GRect(EYE_RIGHT_CENTER+20, EYES_HEIGHT-40, EYE_RIGHT_CENTER+60, EYES_HEIGHT-20), GTextOverflowModeTrailingEllipsis, GTextAlignmentLeft, NULL); } else { GRect rect_bounds = GRect(EYE_LEFT_CENTER, EYES_HEIGHT+10, EYE_RIGHT_CENTER-EYE_LEFT_CENTER, 5); int32_t angle_start = DEG_TO_TRIGANGLE(85); int32_t angle_end = DEG_TO_TRIGANGLE(275); graphics_draw_arc(ctx, rect_bounds, GOvalScaleModeFillCircle, angle_start, angle_end); } }
static void dial_widget_layer_update(DialWidgetLayer *dial_widget_layer, GContext *ctx) { GRect bounds = layer_get_bounds(dial_widget_layer); DialWidgetData *data = (DialWidgetData*)layer_get_data(dial_widget_layer); uint16_t direction = data->vec->direction; // string formatting char center_text[MAX_CENTER_TEXT]; snprintf(center_text, MAX_CENTER_TEXT*sizeof(char), "%u\n%s", data->vec->magnitude, data->units); graphics_context_set_fill_color(ctx, GColorCobaltBlue); graphics_context_set_stroke_color(ctx, GColorBlack); // draw the dial outline graphics_draw_arc(ctx, grect_inset(bounds, GEdgeInsets(1)), GOvalScaleModeFitCircle, 0, DEG_TO_TRIGANGLE(360)); graphics_draw_arc(ctx, grect_inset(bounds, GEdgeInsets(8)), GOvalScaleModeFitCircle, 0, DEG_TO_TRIGANGLE(360)); // draw the arrow graphics_fill_radial(ctx, bounds, GOvalScaleModeFitCircle, 8, DEG_TO_TRIGANGLE(direction - 15), DEG_TO_TRIGANGLE(direction + 15)); // draw the center text GFont font = fonts_get_system_font(FONT_KEY_GOTHIC_14); graphics_context_set_text_color(ctx, GColorBlack); graphics_draw_text(ctx, center_text, font, grect_inset(bounds, GEdgeInsets(8)), GTextOverflowModeWordWrap, GTextAlignmentCenter, NULL); }
static void score_layer_update(Layer *layer,GContext *ctx){ const uint8_t RADIUS = 60; const uint8_t THICKNESS = 10; graphics_context_set_stroke_color(ctx, GColorDarkGray); graphics_context_set_stroke_width(ctx,THICKNESS); GRect r = layer_get_bounds(layer); GPoint center = grect_center_point(&r); graphics_draw_circle(ctx,center,RADIUS); graphics_draw_arc(ctx,center,RADIUS+ (THICKNESS/2),THICKNESS,angle_270,angle_90,GColorDukeBlue); }
void day_display_layer_update_callback(Layer *me, GContext* ctx) { (void)me; PblTm t; get_time(&t); int daysInMonth = t.tm_mon == 3 || t.tm_mon == 5 || t.tm_mon == 8 || t.tm_mon == 10 ? 30 : t.tm_mon != 1 ? 31: t.tm_year % 4 == 0 && (t.tm_year % 400 == 0 || t.tm_year % 100 != 0) ? 29 : 28; unsigned int angle = (t.tm_mday * 180) / daysInMonth; GPoint center = grect_center_point(&me->frame); center.y += 10; graphics_context_set_fill_color(ctx, GColorWhite); graphics_draw_arc(ctx, center, 62, 10, 0, angle); //graphics_draw_line(ctx, GPoint(27, center.y), GPoint(50, center.y)); //graphics_draw_line(ctx, GPoint(94, center.y), GPoint(117, center.y)); for (int x = -1; x < 3; x++) for (int y = -1; y < 3; y++) if (x + y > -2 && x + y < 4 && x - y < 3 && y - x < 3) { graphics_draw_pixel(ctx, GPoint(center.x - 00 + x, center.y + 66 + y)); graphics_draw_pixel(ctx, GPoint(center.x - 47 + x, center.y + 47 + y)); graphics_draw_pixel(ctx, GPoint(center.x + 47 + x, center.y + 47 + y)); } for (int x = 0; x < 2; x++) for (int y = 0; y < 2; y++) { graphics_draw_pixel(ctx, GPoint(center.x - 64 + x, center.y + 17 + y)); graphics_draw_pixel(ctx, GPoint(center.x - 57 + x, center.y + 33 + y)); graphics_draw_pixel(ctx, GPoint(center.x - 33 + x, center.y + 57 + y)); graphics_draw_pixel(ctx, GPoint(center.x - 17 + x, center.y + 64 + y)); graphics_draw_pixel(ctx, GPoint(center.x + 64 + x, center.y + 17 + y)); graphics_draw_pixel(ctx, GPoint(center.x + 57 + x, center.y + 33 + y)); graphics_draw_pixel(ctx, GPoint(center.x + 33 + x, center.y + 57 + y)); graphics_draw_pixel(ctx, GPoint(center.x + 17 + x, center.y + 64 + y)); } }
void hour_display_layer_update_callback(Layer *me, GContext* ctx) { (void)me; PblTm t; get_time(&t); unsigned int angle = (t.tm_hour % 12) * 15 + 180; GPoint center = grect_center_point(&me->frame); center.y -= 10; graphics_context_set_fill_color(ctx, GColorWhite); graphics_draw_arc(ctx, center, 62, 10, 180, angle); //graphics_draw_line(ctx, GPoint(7, center.y), GPoint(20, center.y)); //graphics_draw_line(ctx, GPoint(124, center.y), GPoint(137, center.y)); for (int x = -1; x < 3; x++) for (int y = -1; y < 3; y++) if (x + y > -2 && x + y < 4 && x - y < 3 && y - x < 3) { graphics_draw_pixel(ctx, GPoint(center.x - 00 + x, center.y - 66 + y)); graphics_draw_pixel(ctx, GPoint(center.x - 47 + x, center.y - 47 + y)); graphics_draw_pixel(ctx, GPoint(center.x + 47 + x, center.y - 47 + y)); } for (int x = 0; x < 2; x++) for (int y = 0; y < 2; y++) { graphics_draw_pixel(ctx, GPoint(center.x - 64 + x, center.y - 17 + y)); graphics_draw_pixel(ctx, GPoint(center.x - 57 + x, center.y - 33 + y)); graphics_draw_pixel(ctx, GPoint(center.x - 33 + x, center.y - 57 + y)); graphics_draw_pixel(ctx, GPoint(center.x - 17 + x, center.y - 64 + y)); graphics_draw_pixel(ctx, GPoint(center.x + 64 + x, center.y - 17 + y)); graphics_draw_pixel(ctx, GPoint(center.x + 57 + x, center.y - 33 + y)); graphics_draw_pixel(ctx, GPoint(center.x + 33 + x, center.y - 57 + y)); graphics_draw_pixel(ctx, GPoint(center.x + 17 + x, center.y - 64 + y)); } }
static void arc_update_proc(Layer *layer, GContext *ctx) { GRect bounds = layer_get_bounds(layer); Arc *arc = (Arc*) layer_get_data(layer); GRect rect = GRect( bounds.size.w / 2 - arc->radius, bounds.size.h / 2 - arc->radius - MARGIN, arc->radius * 2, arc->radius * 2 ); graphics_context_set_stroke_color(ctx, INVERT_COLOURS ? GColorBlack : GColorWhite); graphics_context_set_stroke_width(ctx, CIRCLE_THICKNESS); graphics_draw_arc( ctx, rect, GOvalScaleModeFitCircle, 0, DEG_TO_TRIGANGLE(360 * arc->percent) ); }
//----------------------------------------------------------------------------------------------------------------------- static void face_update_proc(Layer *layer, GContext *ctx) { GRect bounds = layer_get_bounds(layer); GPoint center = grect_center_point(&bounds), clock_center = GPoint(200, 200); //Draw Mask #if defined(PBL_RECT) if (CfgData.circle) graphics_draw_bitmap_in_rect(ctx, bmp_mask, bounds); #endif graphics_context_set_stroke_color(ctx, CfgData.circle || CfgData.inv ? GColorBlack : GColorWhite); graphics_context_set_text_color(ctx, CfgData.circle || CfgData.inv ? GColorBlack : GColorWhite); graphics_context_set_fill_color(ctx, CfgData.circle || CfgData.inv ? GColorBlack : GColorWhite); //TRIG_MAX_ANGLE * t->tm_sec / 60 int32_t angle = (TRIG_MAX_ANGLE * (((aktHH % 12) * 60) + (aktMM / 1))) / (12 * 60), sinl = sin_lookup(angle), cosl = cos_lookup(angle); int16_t radV = 144, radD = 175, radT = 135; GPoint sub_center, ptLin, ptDot; sub_center.x = (int16_t)(sinl * (int32_t)radV / TRIG_MAX_RATIO) + clock_center.x; sub_center.y = (int16_t)(-cosl * (int32_t)radV / TRIG_MAX_RATIO) + clock_center.y; GRect sub_rect = { .origin = GPoint(sub_center.x - bounds.size.w / 2, sub_center.y - bounds.size.h / 2), .size = bounds.size }; for (int32_t i = 1; i<=72; i++) { int32_t angleC = TRIG_MAX_ANGLE * i / 72, sinC = sin_lookup(angleC), cosC = cos_lookup(angleC); ptLin.x = (int16_t)(sinC * (int32_t)(radD) / TRIG_MAX_RATIO) + clock_center.x - sub_rect.origin.x; ptLin.y = (int16_t)(-cosC * (int32_t)(radD) / TRIG_MAX_RATIO) + clock_center.y - sub_rect.origin.y; if (ptLin.x > -40 && ptLin.x < bounds.size.w+40 && ptLin.y > -40 && ptLin.y < bounds.size.h+40) { if ((i % 6) == 0) { gpath_move_to(hour_path, ptLin); gpath_rotate_to(hour_path, angleC); gpath_draw_filled(ctx, hour_path); int16_t nHrPnt = i/6; if (clock_is_24h_style()) if ((aktHH > 9 && aktHH < 21 && nHrPnt > 0 && nHrPnt < 6) || (((aktHH > 15 && aktHH <= 23) || (aktHH >= 0 && aktHH < 3)) && nHrPnt >= 6 && nHrPnt <= 12)) nHrPnt += 12; snprintf(hhBuffer, sizeof(hhBuffer), "%d", nHrPnt); GSize txtSize = graphics_text_layout_get_content_size(hhBuffer, fonts_get_system_font(FONT_KEY_DROID_SERIF_28_BOLD), bounds, GTextOverflowModeWordWrap, GTextAlignmentCenter); ptDot.x = (int16_t)(sinC * (int32_t)radT / TRIG_MAX_RATIO) + clock_center.x - sub_rect.origin.x; ptDot.y = (int16_t)(-cosC * (int32_t)radT / TRIG_MAX_RATIO) + clock_center.y - sub_rect.origin.y; graphics_draw_text(ctx, hhBuffer, fonts_get_system_font(FONT_KEY_DROID_SERIF_28_BOLD), GRect(ptDot.x-txtSize.w/2, ptDot.y-txtSize.h/2, txtSize.w, txtSize.h), GTextOverflowModeWordWrap, GTextAlignmentCenter, NULL); } else if ((i % 3) == 0) { gpath_move_to(mins_path, ptLin); gpath_rotate_to(mins_path, angleC); gpath_draw_filled(ctx, mins_path); } else { gpath_move_to(secs_path, ptLin); gpath_rotate_to(secs_path, angleC); gpath_draw_filled(ctx, secs_path); } } } //Draw Hand Path ptLin.x = (int16_t)(sinl * (int32_t)(radV+111) / TRIG_MAX_RATIO) + clock_center.x - sub_rect.origin.x; ptLin.y = (int16_t)(-cosl * (int32_t)(radV+111) / TRIG_MAX_RATIO) + clock_center.y - sub_rect.origin.y; #ifdef PBL_COLOR graphics_context_set_fill_color(ctx, GColorOrange); #else graphics_context_set_fill_color(ctx, CfgData.circle || CfgData.inv ? GColorBlack : GColorWhite); #endif gpath_move_to(hand_path, ptLin); gpath_rotate_to(hand_path, angle); gpath_draw_filled(ctx, hand_path); //Only if no Mask... if (!CfgData.circle) { graphics_context_set_stroke_color(ctx, CfgData.inv ? GColorWhite : GColorBlack); gpath_draw_outline(ctx, hand_path); } //Draw Separator Lines graphics_context_set_stroke_color(ctx, CfgData.inv ? GColorBlack : GColorWhite); #if defined(PBL_RECT) if (CfgData.sep && !CfgData.circle) graphics_draw_line(ctx, GPoint(10, bounds.size.h-1), GPoint(bounds.size.w-10, bounds.size.h-1)); #elif defined(PBL_ROUND) //Radio & Battery graphics_context_set_fill_color(ctx, CfgData.inv ? GColorWhite : GColorBlack); if (CfgData.smart) { graphics_fill_radial(ctx, GRect(-20, center.y-20, 40, 40), GOvalScaleModeFitCircle, 20, DEG_TO_TRIGANGLE(5), DEG_TO_TRIGANGLE(175)); graphics_fill_radial(ctx, GRect(bounds.size.w-20, center.y-20, 40, 40), GOvalScaleModeFitCircle, 20, DEG_TO_TRIGANGLE(185), DEG_TO_TRIGANGLE(355)); if (CfgData.sep) { graphics_draw_arc(ctx, GRect(-20, center.y-20, 40, 40), GOvalScaleModeFitCircle, DEG_TO_TRIGANGLE(5), DEG_TO_TRIGANGLE(175)); graphics_draw_arc(ctx, GRect(bounds.size.w-20, center.y-20, 40, 40), GOvalScaleModeFitCircle, DEG_TO_TRIGANGLE(190), DEG_TO_TRIGANGLE(350)); } } //DateTime if (!CfgData.fsm) { graphics_fill_radial(ctx, GRect(center.x-100, bounds.size.h-n_bottom_margin-5, 200, 200), GOvalScaleModeFitCircle, n_bottom_margin+5, DEG_TO_TRIGANGLE(275), DEG_TO_TRIGANGLE(445)); graphics_draw_text(ctx, ddmmyyyyBuffer, digitS, GRect(0, bounds.size.h-n_bottom_margin-5, bounds.size.w, n_bottom_margin), GTextOverflowModeWordWrap, GTextAlignmentCenter, NULL); if (CfgData.sep) graphics_draw_arc(ctx, GRect(center.x-100, bounds.size.h-n_bottom_margin-5, 200, 200), GOvalScaleModeFitCircle, DEG_TO_TRIGANGLE(275), DEG_TO_TRIGANGLE(445)); } #endif } //----------------------------------------------------------------------------------------------------------------------- static void handle_tick(struct tm *tick_time, TimeUnits units_changed) { if (b_initialized) { aktHH = tick_time->tm_hour; aktMM = tick_time->tm_min; layer_mark_dirty(face_layer); } #if defined(PBL_RECT) strftime(ddmmyyyyBuffer, sizeof(ddmmyyyyBuffer), //true ? "%a %d.%b" : CfgData.datefmt == 1 ? "%d-%m-%Y" : CfgData.datefmt == 2 ? "%d/%m/%Y" : CfgData.datefmt == 3 ? "%m/%d/%Y" : CfgData.datefmt == 4 ? "%Y-%m-%d" : CfgData.datefmt == 5 ? "%d.%m.%y" : CfgData.datefmt == 6 ? "%d-%m-%y" : CfgData.datefmt == 7 ? "%d/%m/%y" : CfgData.datefmt == 8 ? "%m/%d/%y" : CfgData.datefmt == 9 ? "%y-%m-%d" : CfgData.datefmt == 10 ? "%a %d.%m." : CfgData.datefmt == 11 ? "%a %d.%b" : "%d.%m.%Y", tick_time); #elif defined(PBL_ROUND) strftime(ddmmyyyyBuffer, sizeof(ddmmyyyyBuffer), //true ? "%a %d." : CfgData.datefmt == 1 ? "%d-%m" : CfgData.datefmt == 2 ? "%d/%m" : CfgData.datefmt == 3 ? "%m/%d" : CfgData.datefmt == 4 ? "%m-%d" : CfgData.datefmt == 5 ? "%d.%m" : CfgData.datefmt == 6 ? "%d-%m" : CfgData.datefmt == 7 ? "%d/%m" : CfgData.datefmt == 8 ? "%m/%d" : CfgData.datefmt == 9 ? "%m-%d" : CfgData.datefmt == 10 ? "%a %d." : CfgData.datefmt == 11 ? "%a %d." : "%d.%m", tick_time); #endif /* snprintf(ddmmyyyyBuffer, sizeof(ddmmyyyyBuffer), CfgData.datefmt == 1 ? "%d-%d-%d" : CfgData.datefmt == 2 ? "%d/%d/%d" : CfgData.datefmt == 3 ? "%d/%d/%d" : CfgData.datefmt == 4 ? "%d-%d-%d" : "%d.%d.%d", 88, 88, 8888); */ //strcpy(ddmmyyyyBuffer, "00000"); text_layer_set_text(date_layer, ddmmyyyyBuffer); //Hourly vibrate if (CfgData.vibr && tick_time->tm_min == 0) vibes_enqueue_custom_pattern(vibe_pat_hr); } //----------------------------------------------------------------------------------------------------------------------- static void timerCallback(void *data) { if ((int)data == TIMER_ANIM_FACE && !b_initialized) { time_t temp = time(NULL); struct tm *t = localtime(&temp); if ((aktHH % 12) != (t->tm_hour % 12) || aktMM != t->tm_min) { int16_t nStep = (aktHH % 12) != (t->tm_hour % 12) ? 5 : 1; if ((t->tm_hour % 12) < 6) { //Initial Value? Set correct initial if (aktHH == 0 && aktMM == 0) { aktHH = t->tm_hour >= 12 ? 12 : 0; aktMM = 0; } if (aktMM < 60-nStep) aktMM += nStep; else { aktMM = 0; aktHH++; } } else { //Initial Value? Set correct initial if (aktHH == 0 && aktMM == 0) { aktHH = t->tm_hour > 12 ? 23 : 11; aktMM = 60; } if (aktMM > nStep) aktMM -= nStep; else { aktMM = 60; aktHH--; } //Little workaround if time is close to the 12 o'clock if ((aktHH % 12) == (t->tm_hour % 12) && aktMM < t->tm_min) aktMM = t->tm_min; } layer_mark_dirty(face_layer); timer_face = app_timer_register(TIMER_ANIM_FACE_MS, timerCallback, (void*)TIMER_ANIM_FACE); } else b_initialized = true; } else if ((int)data == TIMER_ANIM_BATT && b_charging) { int nImage = 10 - (aktBattAnim / 10); bitmap_layer_set_bitmap(battery_layer, NULL); gbitmap_destroy(bmp_batt); bmp_batt = gbitmap_create_as_sub_bitmap(batteryAll, GRect(10*nImage, 0, 10, 20)); bitmap_layer_set_bitmap(battery_layer, bmp_batt); aktBattAnim += 10; if (aktBattAnim > 100) aktBattAnim = aktBatt; timer_batt = app_timer_register(TIMER_ANIM_BATT_MS, timerCallback, (void*)TIMER_ANIM_BATT); } } //----------------------------------------------------------------------------------------------------------------------- void battery_state_service_handler(BatteryChargeState charge_state) { int nImage = 0; aktBatt = charge_state.charge_percent; if (charge_state.is_charging) { if (!b_charging) { nImage = 10; b_charging = true; aktBattAnim = aktBatt; timer_batt = app_timer_register(TIMER_ANIM_BATT_MS, timerCallback, (void*)TIMER_ANIM_BATT); } } else { nImage = 10 - (aktBatt / 10); b_charging = false; } bmp_batt = gbitmap_create_as_sub_bitmap(batteryAll, GRect(10*nImage, 0, 10, 20)); bitmap_layer_set_bitmap(battery_layer, bmp_batt); }
/*\ |*| DrawArc function thanks to Cameron MacFarland (http://forums.getpebble.com/profile/12561/Cameron%20MacFarland) \*/ void graphics_draw_arc(GContext *ctx, GPoint center, int radius, int thickness, int start_angle, int end_angle, GColor c) { int32_t xmin = 65535000, xmax = -65535000, ymin = 65535000, ymax = -65535000; int32_t cosStart, sinStart, cosEnd, sinEnd; int32_t r, t; while (start_angle < 0) start_angle += TRIG_MAX_ANGLE; while (end_angle < 0) end_angle += TRIG_MAX_ANGLE; start_angle %= TRIG_MAX_ANGLE; end_angle %= TRIG_MAX_ANGLE; if (end_angle == 0) end_angle = TRIG_MAX_ANGLE; if (start_angle > end_angle) { graphics_draw_arc(ctx, center, radius, thickness, start_angle, TRIG_MAX_ANGLE, c); graphics_draw_arc(ctx, center, radius, thickness, 0, end_angle, c); } else { // Calculate bounding box for the arc to be drawn cosStart = cos_lookup(start_angle); sinStart = sin_lookup(start_angle); cosEnd = cos_lookup(end_angle); sinEnd = sin_lookup(end_angle); r = radius; // Point 1: radius & start_angle t = r * cosStart; if (t < xmin) xmin = t; if (t > xmax) xmax = t; t = r * sinStart; if (t < ymin) ymin = t; if (t > ymax) ymax = t; // Point 2: radius & end_angle t = r * cosEnd; if (t < xmin) xmin = t; if (t > xmax) xmax = t; t = r * sinEnd; if (t < ymin) ymin = t; if (t > ymax) ymax = t; r = radius - thickness; // Point 3: radius-thickness & start_angle t = r * cosStart; if (t < xmin) xmin = t; if (t > xmax) xmax = t; t = r * sinStart; if (t < ymin) ymin = t; if (t > ymax) ymax = t; // Point 4: radius-thickness & end_angle t = r * cosEnd; if (t < xmin) xmin = t; if (t > xmax) xmax = t; t = r * sinEnd; if (t < ymin) ymin = t; if (t > ymax) ymax = t; // Normalization xmin /= TRIG_MAX_RATIO; xmax /= TRIG_MAX_RATIO; ymin /= TRIG_MAX_RATIO; ymax /= TRIG_MAX_RATIO; // Corrections if arc crosses X or Y axis if ((start_angle < angle_90) && (end_angle > angle_90)) { ymax = radius; } if ((start_angle < angle_180) && (end_angle > angle_180)) { xmin = -radius; } if ((start_angle < angle_270) && (end_angle > angle_270)) { ymin = -radius; } // Slopes for the two sides of the arc float sslope = (float)cosStart/ (float)sinStart; float eslope = (float)cosEnd / (float)sinEnd; if (end_angle == TRIG_MAX_ANGLE) eslope = -1000000; int ir2 = (radius - thickness) * (radius - thickness); int or2 = radius * radius; graphics_context_set_stroke_color(ctx, c); for (int x = xmin; x <= xmax; x++) { for (int y = ymin; y <= ymax; y++) { int x2 = x * x; int y2 = y * y; if ( (x2 + y2 < or2 && x2 + y2 >= ir2) && ( (y > 0 && start_angle < angle_180 && x <= y * sslope) || (y < 0 && start_angle > angle_180 && x >= y * sslope) || (y < 0 && start_angle <= angle_180) || (y == 0 && start_angle <= angle_180 && x < 0) || (y == 0 && start_angle == 0 && x > 0) ) && ( (y > 0 && end_angle < angle_180 && x >= y * eslope) || (y < 0 && end_angle > angle_180 && x <= y * eslope) || (y > 0 && end_angle >= angle_180) || (y == 0 && end_angle >= angle_180 && x < 0) || (y == 0 && start_angle == 0 && x > 0) ) ) graphics_draw_pixel(ctx, GPoint(center.x+x, center.y+y)); } } } }
static void update_layer_callback(Layer *layer, GContext* ctx) { GRect bounds = layer_get_frame(layer); // minutes = 59; graphics_context_set_fill_color(ctx, GColorWhite); graphics_context_set_stroke_color(ctx, GColorWhite); // Draw minutes arc int32_t minutes_angle = 360 * minutes / 60; if(minutes_angle <= 90){ graphics_draw_arc(ctx, center, INNER_RADIUS, INNER_RADIUS, 270, 270 + minutes_angle); } else { graphics_draw_arc(ctx, center, INNER_RADIUS, INNER_RADIUS, 270, 360); graphics_draw_arc(ctx, center, INNER_RADIUS, INNER_RADIUS, 0, minutes_angle - 90); } // Draw bitmap pattern graphics_context_set_compositing_mode(ctx, GCompOpAnd); graphics_draw_bitmap_in_rect(ctx, image, bounds); // Draw hours arc int32_t hours_angle = 360 * ((hours % 12) * 60 + minutes) / (12 * 60); if(hours_angle <= 90){ graphics_draw_arc(ctx, center, OUTER_RADIUS, OUTER_THICKNESS, 270, 270 + hours_angle); } else { graphics_draw_arc(ctx, center, OUTER_RADIUS, OUTER_THICKNESS, 270, 360); graphics_draw_arc(ctx, center, OUTER_RADIUS, OUTER_THICKNESS, 0, hours_angle - 90); } graphics_draw_pixel(ctx, GPoint(center.x-1, center.y - OUTER_RADIUS + 2)); // round end effect graphics_draw_pixel(ctx, GPoint(center.x-1, center.y - OUTER_RADIUS + 3)); // round end effect // Draw hour dot GPoint hourDot; hours_angle = TRIG_MAX_ANGLE * ((hours % 12) * 60 + minutes) / (12 * 60); hourDot.y = (int16_t)(-cos_lookup(hours_angle) * (OUTER_RADIUS - OUTER_THICKNESS/2) / TRIG_MAX_RATIO) + center.y; hourDot.x = (int16_t)(sin_lookup(hours_angle) * (OUTER_RADIUS - OUTER_THICKNESS/2) / TRIG_MAX_RATIO) + center.x; graphics_context_set_fill_color(ctx, GColorWhite); graphics_fill_circle(ctx, hourDot, DOT_RADIUS); if(hours >= 12){ graphics_context_set_fill_color(ctx, GColorBlack); graphics_fill_circle(ctx, hourDot, DOT_RADIUS - 2); } // Draw center dot if bluetooth connected if(bluetooth_connected){ graphics_context_set_fill_color(ctx, GColorBlack); graphics_fill_circle(ctx, center, DOT_RADIUS + 3); graphics_context_set_fill_color(ctx, GColorWhite); graphics_fill_circle(ctx, center, DOT_RADIUS); graphics_context_set_fill_color(ctx, GColorBlack); graphics_fill_circle(ctx, center, DOT_RADIUS - 2); } else { graphics_context_set_fill_color(ctx, GColorBlack); graphics_fill_rect(ctx, GRect(center.x - (DOT_RADIUS + 4), center.y - (DOT_RADIUS + 4), 2*(DOT_RADIUS + 4), 2*(DOT_RADIUS + 4)), 0, 0); graphics_context_set_fill_color(ctx, GColorWhite); graphics_fill_rect(ctx, GRect(center.x - DOT_RADIUS, center.y - DOT_RADIUS, 2*DOT_RADIUS, 2*DOT_RADIUS), 0, 0); graphics_context_set_fill_color(ctx, GColorBlack); graphics_fill_rect(ctx, GRect(center.x - (DOT_RADIUS - 2), center.y - (DOT_RADIUS - 2), 2*(DOT_RADIUS - 2), 2*(DOT_RADIUS - 2)), 0, 0); } // Draw dates graphics_context_set_text_color(ctx, GColorWhite); graphics_draw_text(ctx, date_str, custom_font, GRect(0, 142, 144, 23), GTextOverflowModeWordWrap, GTextAlignmentCenter, NULL); }