Пример #1
0
Файл: main.c Проект: j0hax/Braun
// Draws hands onto the given layer
static void draw_hands(Layer* layer, GContext* ctx) {
  gpath_rotate_to(hour_ptr, (TRIG_MAX_ANGLE * timedata[0] / 12) + (TRIG_MAX_ANGLE * timedata[1] / 720.0f));
  graphics_context_set_fill_color(ctx, GColorWhite);
  gpath_draw_filled(ctx, hour_ptr);
  // minute hand
  gpath_rotate_to(minute_ptr, (TRIG_MAX_ANGLE * timedata[1] / 60) + (TRIG_MAX_ANGLE * timedata[2] / 3600.0f));
  graphics_context_set_fill_color(ctx, GColorWhite);
  gpath_draw_filled(ctx, minute_ptr);
  
  // seconds get some extra attention here-- the same as above, but with an extra little counterweight type thing on the opposite site
  GPoint sec0 = (GPoint) {
    .x = (int16_t)(center.x + -sin_lookup(TRIG_MAX_ANGLE * timedata[2] / 60) * 18 / TRIG_MAX_RATIO),
     .y = (int16_t)(center.y + cos_lookup(TRIG_MAX_ANGLE * timedata[2] / 60) * 18 / TRIG_MAX_RATIO)
  };
  GPoint sec1 = (GPoint) {
    .x = (int16_t)(center.x + sin_lookup(TRIG_MAX_ANGLE * timedata[2] / 60) * 72 / TRIG_MAX_RATIO), .y = (int16_t)(center.y + -cos_lookup(TRIG_MAX_ANGLE * timedata[2] / 60) * 72 / TRIG_MAX_RATIO)
  };
  graphics_context_set_stroke_color(ctx, GColorYellow );
  graphics_context_set_stroke_width(ctx, 3);
  graphics_draw_line(ctx, center, sec1);
  graphics_context_set_stroke_width(ctx, 6);
  graphics_draw_line(ctx, center, sec0);
  graphics_context_set_fill_color(ctx, GColorYellow );
  graphics_fill_circle(ctx, center, 5);
  graphics_context_set_stroke_color(ctx, GColorBlack);
  graphics_draw_pixel(ctx, center);
}

// draws face onto the given layer
static void draw_face(Layer* layer, GContext* ctx) {
  
  static char buf[] = "00";
  
  graphics_context_set_stroke_color(ctx, GColorLightGray);

  // draw 60 minute ticks around clock
  for (int i = 0; i < 60; i++) {
    // tic0 = start of inner point
    // tic1 = end of outer point
    GPoint tic0, tic1;

    // tic0 is the starting point from center, tic1 is the outer point of the tic
    if (i % 5 == 0) {
      // hour
      tic0 = (GPoint) {
        .x = (int16_t)(center.x + sin_lookup(TRIG_MAX_ANGLE * i / 60) * 69 / TRIG_MAX_RATIO),
         .y = (int16_t)(center.y + -cos_lookup(TRIG_MAX_ANGLE * i / 60) * 69 / TRIG_MAX_RATIO)
      };
      tic1 = (GPoint) {
        .x = (int16_t)(tic0.x + sin_lookup(TRIG_MAX_ANGLE * i / 60) * 15 / TRIG_MAX_RATIO),
         .y = (int16_t)(tic0.y + -cos_lookup(TRIG_MAX_ANGLE * i / 60) * 15 / TRIG_MAX_RATIO)
      };
      graphics_context_set_stroke_width(ctx, 2);
      
      /*if (i != 30) {
        GRect HourText = GRect((int16_t)(center.x + sin_lookup(TRIG_MAX_ANGLE * i / 60) * 54 / TRIG_MAX_RATIO)-10,
                               (int16_t)(center.y + -cos_lookup(TRIG_MAX_ANGLE * i / 60) * 54 / TRIG_MAX_RATIO)-10,
                               20, 20);
        
        snprintf(buf, sizeof(buf), "%d", i/5);
        graphics_context_set_text_color(ctx, GColorWhite);
        graphics_draw_text(ctx, buf, fonts_get_system_font(FONT_KEY_GOTHIC_18),
                       HourText, GTextOverflowModeWordWrap,
                       GTextAlignmentCenter, NULL);
        
      }*/

    } else {
      // minute marks
      tic0 = (GPoint) {
        .x = (int16_t)(center.x + sin_lookup(TRIG_MAX_ANGLE * i / 60) * 74 / TRIG_MAX_RATIO),
         .y = (int16_t)(center.y + -cos_lookup(TRIG_MAX_ANGLE * i / 60) * 74 / TRIG_MAX_RATIO)
      };
      tic1 = (GPoint) {
        .x = (int16_t)(tic0.x + sin_lookup(TRIG_MAX_ANGLE * i / 60) * 10 / TRIG_MAX_RATIO),
         .y = (int16_t)(tic0.y + -cos_lookup(TRIG_MAX_ANGLE * i / 60) * 10 / TRIG_MAX_RATIO)
      };
      graphics_context_set_stroke_width(ctx, 1);
    }

    graphics_draw_line(ctx, tic0, tic1);
  }

  // draw the date (new and complex how scary)
  snprintf(buf, sizeof(buf), "%d", timedata[3]);
  int yDate = center.y + layer_get_frame(s_face_layer).size.h / 4;
  int xDate = center.x - 6;
  GRect date_window = GRect(xDate, yDate, 13, 18);
  graphics_context_set_fill_color(ctx, GColorWhite);
  graphics_context_set_text_color(ctx, GColorBlack);
  graphics_fill_rect(ctx, date_window, 0, 0);
  graphics_draw_text(ctx, buf, fonts_get_system_font(FONT_KEY_GOTHIC_14),
                     date_window, GTextOverflowModeWordWrap,
                     GTextAlignmentCenter, NULL);
  graphics_context_set_fill_color(ctx, GColorRed);
  gpath_move_to(chevron, GPoint(xDate + 6, yDate - 3));
  gpath_rotate_to(chevron, TRIG_MAX_ANGLE * 0.5f);
  gpath_draw_filled(ctx, chevron);
}

static void tick_handler(struct tm* tick_time, TimeUnits units_changed) {
  // just store the time, don't bother with making a new one in the update_proc or calling update_time
  timedata[0] = tick_time->tm_hour % 12;
  timedata[1] = tick_time->tm_min;
  timedata[2] = tick_time->tm_sec;
  timedata[3] = tick_time->tm_mday;
  layer_mark_dirty(s_hands_layer);
}

static void main_window_load(Window* window) {
  // self-explanatory: make the main window black with one full-screen layer to display the time
  window_set_background_color(window, GColorBlack);
  s_face_layer = layer_create(layer_get_bounds(window_get_root_layer(s_window)));
  s_hands_layer = layer_create(layer_get_bounds(window_get_root_layer(s_window)));
  logo = gbitmap_create_with_resource(RESOURCE_ID_LOGO);
  int offset = (center.x-20);
  logo_layer = bitmap_layer_create(GRect(offset, 50, 40, 12));
  bitmap_layer_set_bitmap(logo_layer, logo);
  layer_add_child(s_face_layer, bitmap_layer_get_layer(logo_layer));
  layer_set_update_proc(s_face_layer, draw_face);
  layer_set_update_proc(s_hands_layer, draw_hands);
  layer_add_child(window_get_root_layer(window), s_face_layer);
  layer_add_child(window_get_root_layer(window), s_hands_layer);
}

static void main_window_unload(Window* window) {
  gbitmap_destroy(logo);
  bitmap_layer_destroy(logo_layer);
  layer_destroy(s_face_layer);
  layer_destroy(s_hands_layer);
  gpath_destroy(hour_ptr);
  gpath_destroy(minute_ptr);
  gpath_destroy(second_ptr);
}

static void init() {
  // initialize stuff you know the drill
  s_window = window_create();
  window_set_window_handlers(s_window, (WindowHandlers) {
    .load = main_window_load,
     .unload = main_window_unload
  });
Пример #2
0
static void hands_update_proc(Layer *layer, GContext *ctx) {

  time_t now = time(NULL);
  struct tm *t = localtime(&now);
  
  GRect bounds = layer_get_bounds(layer);
  GPoint center = grect_center_point(&bounds);
  int32_t second_angle = (TRIG_MAX_ANGLE * (((t->tm_hour % 12) * 6) + (t->tm_min / 10))) / (12 * 6);
  
  GPoint second_hand = {
    .x = (int16_t)(-sin_lookup(second_angle) * -45 / TRIG_MAX_RATIO) + center.x,
    .y = (int16_t)(cos_lookup(second_angle) * -45 / TRIG_MAX_RATIO) + center.y,
  };

  #ifdef PBL_COLOR
    graphics_context_set_stroke_color(ctx, GColorYellow);
    graphics_context_set_fill_color(ctx, GColorYellow);
  #else
    graphics_context_set_stroke_color(ctx, GColorWhite);
    graphics_context_set_fill_color(ctx, GColorWhite);
  #endif
    
  graphics_draw_circle(ctx, second_hand, 4);
  graphics_fill_circle(ctx, second_hand, 4);
   
/*  // HOUR HAND //
  gpath_rotate_to(s_hour_arrow, (TRIG_MAX_ANGLE * (((t->tm_hour % 12) * 6) + (t->tm_min / 10))) / (12 * 6));
  #ifdef PBL_COLOR
    graphics_context_set_fill_color(ctx, GColorYellow);
    graphics_context_set_stroke_color(ctx, GColorYellow);
  #else
    graphics_context_set_fill_color(ctx, GColorWhite);
    graphics_context_set_stroke_color(ctx, GColorWhite);
  #endif
  gpath_draw_filled(ctx, s_hour_arrow);
  gpath_draw_outline(ctx, s_hour_arrow);
*/  
  // MINUTE HAND //
  gpath_rotate_to(s_minute_arrow, TRIG_MAX_ANGLE * t->tm_min / 60);
  #ifdef PBL_COLOR
    graphics_context_set_fill_color(ctx, GColorWhite);
    graphics_context_set_stroke_color(ctx, GColorWhite);
  #else
    graphics_context_set_fill_color(ctx, GColorWhite);
    graphics_context_set_stroke_color(ctx, GColorWhite);
  #endif
  gpath_draw_filled(ctx, s_minute_arrow);
  gpath_draw_outline(ctx, s_minute_arrow);

  // SECOND HAND //
  gpath_rotate_to(s_second_arrow, (TRIG_MAX_ANGLE * t->tm_sec / 60));
  #ifdef PBL_COLOR
    graphics_context_set_fill_color(ctx, GColorRed);
    graphics_context_set_stroke_color(ctx, GColorRed);
  #else
    graphics_context_set_fill_color(ctx, GColorWhite);
    graphics_context_set_stroke_color(ctx, GColorWhite);
  #endif
  gpath_draw_filled(ctx, s_second_arrow);
  gpath_draw_outline(ctx, s_second_arrow);
 
  if(clock_is_24h_style() == true) {
    //Use 2h hour format
    strftime(buffer, sizeof("00:00"), "%H:%M", t);
  } else {
    //Use 12 hour format
    strftime(buffer, sizeof("00:00"), "%I:%M", t);
  }       
 
  strftime(date, sizeof("XXX XX"), "%a %d", t);
  text_layer_set_text(date_layer, date);
  text_layer_set_text(time_layer, buffer);

}

static void handle_second_tick(struct tm *tick_time, TimeUnits units_changed) {
  layer_mark_dirty(window_get_root_layer(window));
}
Пример #3
0
int dy(float angle, int radius){
  return -cos_lookup(angle) * radius / TRIG_MAX_RATIO;
}
Пример #4
0
static void hands_update_proc(Layer *layer, GContext *ctx) {
  time_t now = time(NULL);
  struct tm *t = localtime(&now);
  
  graphics_context_set_stroke_color(ctx, hand_color);
  
  #ifdef PBL_COLOR
    graphics_context_set_antialiased(ctx, false);
  #endif
  
  GRect bounds = layer_get_bounds(layer);
  GPoint center = grect_center_point(&bounds);
  
  //minute hand
  int16_t hand_length = bounds.size.w / 2 ;
  int32_t angle = TRIG_MAX_ANGLE * t->tm_min / 60;
  GPoint hand = {
    .x = (int16_t)(sin_lookup(angle) * (int32_t)hand_length / TRIG_MAX_RATIO) + center.x,
    .y = (int16_t)(-cos_lookup(angle) * (int32_t)hand_length / TRIG_MAX_RATIO) + center.y,
  };
  #ifdef PBL_COLOR
    graphics_context_set_stroke_width(ctx, 3);
  #endif
  graphics_draw_line(ctx, hand, center);
  
  //hour hand
  hand_length = hand_length - 25;
  angle = (TRIG_MAX_ANGLE * (((t->tm_hour % 12) * 6) + (t->tm_min / 10))) / (12 * 6);
  hand = (GPoint){
    .x = (int16_t)(sin_lookup(angle) * (int32_t)hand_length / TRIG_MAX_RATIO) + center.x,
    .y = (int16_t)(-cos_lookup(angle) * (int32_t)hand_length / TRIG_MAX_RATIO) + center.y,
  };
  #ifdef PBL_COLOR
   graphics_context_set_stroke_width(ctx, 5);
  #endif
  graphics_draw_line(ctx, hand, center);
  
  #ifndef PBL_RECT
    graphics_context_set_fill_color(ctx, hand_color);
    graphics_fill_circle(ctx, center, 7);
  #endif
  
}



static void handle_second_tick(struct tm *tick_time, TimeUnits units_changed) {
  
  #ifndef PBL_COLOR
     memset(aplite_visited, 0, 168*20);
  #endif
  
 
  //adjusting shadow direction according to minute hand location
  if (tick_time->tm_min >= 0 && tick_time->tm_min < 15) {
    s_effect_offset.offset_x = SHADOW_LENGTH;
    s_effect_offset.offset_y = SHADOW_LENGTH;
  } else if (tick_time->tm_min >= 15 && tick_time->tm_min < 30) {
    s_effect_offset.offset_x = -SHADOW_LENGTH;
    s_effect_offset.offset_y = SHADOW_LENGTH;
  } else if (tick_time->tm_min >= 30 && tick_time->tm_min < 45) {  
    s_effect_offset.offset_x = -SHADOW_LENGTH;
    s_effect_offset.offset_y = -SHADOW_LENGTH;  
  } else {
    s_effect_offset.offset_x = SHADOW_LENGTH;
    s_effect_offset.offset_y = -SHADOW_LENGTH;  
  }  
  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);

  s_hands_layer = layer_create(bounds);
  layer_set_update_proc(s_hands_layer, hands_update_proc);
  layer_add_child(window_layer, s_hands_layer);
  
  //creating shadow layer
  s_effect_offset = (EffectOffset){
    .orig_color = hand_color,
    .offset_color = shadow_color,
    .option = 1
      
    // creating array for "visited" pixels and assigning it to shadow effect parameter
    #ifndef PBL_COLOR  
      ,
      .aplite_visited = aplite_visited
    #endif 
  };
  
  s_effect_layer = effect_layer_create(bounds);
  effect_layer_add_effect(s_effect_layer, effect_shadow, &s_effect_offset);
  effect_layer_add_effect(s_effect_layer, effect_blur, (void*)1);
  layer_add_child(window_layer, effect_layer_get_layer(s_effect_layer));
  
}

static void window_unload(Window *window) {
  layer_destroy(s_hands_layer);
}
Пример #5
0
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);
}
Пример #6
0
//1. Base layer contains coloured analogue watch face
static void bg_update_proc(Layer *layer, GContext *ctx)
{
    GRect bounds = layer_get_bounds(layer);
    int widthHalf = bounds.size.w / 2,
        heightHalf = bounds.size.h / 2;
    int32_t width = bounds.size.w * 3;

    time_t now = time(NULL);
    struct tm *t = localtime(&now);
    hr = t->tm_hour;
    min = t->tm_min;
    //hr = 7; min = 20; //DEBUG
#ifdef DEBUG_MODE
    int sec = t->tm_sec;
    min = sec;
    if (min == 59) --lastSurpriseHr; //force re-selection of surprise min after every round of min hand
#endif
    int32_t angleM = TRIG_MAX_ANGLE * min / 60;
    //int32_t angleH = TRIG_MAX_ANGLE * (hr % 12) / 12; //without minutes contribution
    int32_t angleH = (TRIG_MAX_ANGLE * (((hr % 12) * 6) + (min / 10))) / (12 * 6); //with minutes contribution
    int32_t angleMid;

#ifdef DEBUG_COLOURS
    m_nColourIndex = t->tm_sec * MAX_COLOURS / 60;
#else
    m_nColourIndex = (t->tm_yday * 24 + hr) % MAX_COLOURS;
#endif
    //APP_LOG(APP_LOG_LEVEL_DEBUG, "h:m %d:%d => angles: %d, %d", hr, min, (int) (angleM * 360 / TRIG_MAX_ANGLE), (int) (angleH * 360 / TRIG_MAX_ANGLE));
    bool bIsSmallSectorLight = true;

    if (angleM >= angleH)
    {
        if ((angleM - angleH) <= ANGLE_DEG_180)
        {
            angleMid = (angleM + angleH) / 2;
        }
        else
        {
            bIsSmallSectorLight = false;
            angleMid = (TRIG_MAX_ANGLE - angleM + angleH) / 2 + angleM;
        }
    }
    else //angleH > angleM
    {
        if ((angleH - angleM) <= ANGLE_DEG_180)
        {
            angleMid = (angleM + angleH) / 2;
            bIsSmallSectorLight = false;
        }
        else
        {
            angleMid = (TRIG_MAX_ANGLE - angleH + angleM) / 2 + angleH;
        }
    }

    int mInQ = angleM / ANGLE_DEG_90,
        hInQ = angleH / ANGLE_DEG_90;
    dateQuadrant = DATE_QUAD_INDEX[mInQ][hInQ];
    dateQuadrantUseApc = (mInQ != hInQ)?
        DATE_QUAD_USE_PRI[mInQ][hInQ]: (angleM < angleH);
    surpQuadrant = SURPRISE_QUAD_INDEX[mInQ][hInQ];
    surpQuadrantUseApc = (mInQ != hInQ)?
        SURPRISE_QUAD_USE_PRI[mInQ][hInQ]: (angleM < angleH);

    //create rectangle (for simplicity instead of sector; triangle is insufficient as at wide angles, it won't cover the corner!)
    GPathInfo sectorInfo = {
        .num_points = 4,
        .points = (GPoint []) {
            {0, 0},
            {width * sin_lookup(angleH) / TRIG_MAX_RATIO, -width * cos_lookup(angleH) / TRIG_MAX_RATIO},
            {width * sin_lookup(angleMid) / TRIG_MAX_RATIO, -width * cos_lookup(angleMid) / TRIG_MAX_RATIO},
            {width * sin_lookup(angleM) / TRIG_MAX_RATIO, -width * cos_lookup(angleM) / TRIG_MAX_RATIO}
        } };
    GPath *sector = gpath_create(&sectorInfo);
    GPoint center = grect_center_point(&bounds);
    gpath_move_to(sector, center);

    //bIsSmallSectorLight = ! bIsSmallSectorLight; //try inverting colour scheme to more light (i.e. bigger light sector)
#ifdef INVERT_COLOURS
    GColor clrDark = (GColor8){.argb=COLOURS[m_nColourIndex][1]};
    GColor clrLight = (GColor8){.argb=COLOURS[m_nColourIndex][0]};
#else
    GColor clrDark = (GColor8){.argb=COLOURS[m_nColourIndex][0]};
    GColor clrLight = (GColor8){.argb=COLOURS[m_nColourIndex][1]};
#endif
    //draw background (rest, i.e. big sector)
    graphics_context_set_fill_color(ctx, !bIsSmallSectorLight? clrLight: clrDark);
    graphics_fill_rect(ctx, layer_get_bounds(layer), 0, GCornerNone);

    //draw small sector
    GColor c = bIsSmallSectorLight? clrLight: clrDark;
    graphics_context_set_fill_color(ctx, c);
    graphics_context_set_stroke_color(ctx, c);
    gpath_draw_filled(ctx, sector);
    gpath_draw_outline(ctx, sector);
    gpath_destroy(sector);

    //write 'hour' hint
    strftime(s_hour_buffer, sizeof(s_hour_buffer), "%l", t);
    //strftime(s_hour_buffer, sizeof(s_hour_buffer), "12", t); //DEBUG: Try widest hour displayed: 12

    /**
     * In FONT_KEY_BITHAM_30_BLACK, digit '6' is ~18x21 px.
     * Thus, need vertical offset (of 5 px) as top of font character is 9px down.
     **/
#ifdef DEBUG_HOUR_HINT
    int32_t angle = angleM + ANGLE_HOUR_HINT;
#else
    int32_t angle = angleH + ANGLE_HOUR_HINT;
#endif
    int radius = heightHalf - 18; //less font size & margin
    if (((angle >= ANGLE_DEG_45) && (angle <= ANGLE_DEG_135))
        || ((angle >= ANGLE_DEG_225) && (angle <= ANGLE_DEG_315)))
    {
        radius = widthHalf - 18;
    }
    int i;
    for (i = 0; i < 5; ++i)
    {
        text_layer_set_text(s_hour_label[i], s_hour_buffer);
        GRect frame = layer_get_frame((Layer*)s_hour_label[i]);
        frame.origin.x = OFFSET_OUTLINE[i][0] + center.x - (frame.size.w / 2)
            + radius * sin_lookup(angle) / TRIG_MAX_RATIO;
        frame.origin.y = OFFSET_OUTLINE[i][1] + center.y - (frame.size.h / 2) - 5 //offset 5px up
            - radius * cos_lookup(angle) / TRIG_MAX_RATIO;
        layer_set_frame((Layer*)s_hour_label[i], frame);
        if (i < 4)
        {
            text_layer_set_text_color(s_hour_label[i], (hr >= 12)? GColorBlack: GColorWhite);
        }
        else
        {
            text_layer_set_text_color(s_hour_label[i], (hr >= 12)? GColorWhite: GColorBlack);
        }
    }

    bool bToShowPicFor1stTime = false;
    if (lastSurpriseHr < 0)
    {
        bToShowPicFor1stTime = true; //show pic when watchface is first loaded
    }
    if (bToShowPicFor1stTime || (hr != lastSurpriseHr))
    {
        lastSurpriseHr = hr;
        //randomly pick a min to show surprise pic:
        if (!bToShowPicFor1stTime)
        {
            nextSurpriseMin = rand() % 60;
        }
        else if (nextSurpriseMin < 59) //showing pic for 1st time, so randomly pick a min after current min
        {
            nextSurpriseMin = (rand() % (59 - min)) + min + 1;
        }
        surpriseShownCnt = 0;
    }
    if (bToShowPicFor1stTime
        || ((min == nextSurpriseMin) && (surpriseShownCnt == 0)))
    {
        if (!bToShowPicFor1stTime)
        {
            ++surpriseShownCnt;
        }
        m_bSupriseShowing = true;
        layer_set_hidden(m_sLayerWeather, true);
        bitmap_layer_set_bitmap(m_spbmLayer, m_spbmPics[rand() % MAX_PICS]);
        //move surprise pic to appropriate quadrant:
        moveLayer((Layer*)m_spbmLayer, layer, surpQuadrant);
        m_sptimer1 = app_timer_register(PIC_SHOW_INTERVAL, (AppTimerCallback) hidePic, NULL);
    }

    if (m_bWeatherEnabled)
    {
        moveLayer2((Layer*)m_sLayerWeather, layer, surpQuadrant, !m_bSupriseShowing && m_bWeatherEnabled);
    }

    if ((m_nVibes & MASKV_HOURLY) //option enabled to vibrate hourly
        && (min == 0) //hourly mark reached
        && (m_nLastHourlyShake != now)) //sometimes update proc gets called several times in the same min, so shake only once!
    {
        int from = (m_nVibes & MASKV_FROM) >> 8,
            to = m_nVibes & MASKV_TO;
        bool bShake = false;
        if (from <= to)
        {
            bShake = (hr >= from) && (hr <= to);
        }
        else
        {
            bShake = (hr >= from) || (hr <= to);
        }
        if (bShake)
        {
            m_nLastHourlyShake = now;
            vibes_double_pulse();
        }
    }
}
Пример #7
0
static void hands_update_proc(Layer *layer, GContext *ctx) {
  GRect bounds = layer_get_bounds(layer);
  GPoint center = grect_center_point(&bounds);
  
  time_t now = time(NULL);
  struct tm *t = localtime(&now);
  
  // Date
  if (strcmp(configs.dateoption, "nodate") == 0) {
    layer_set_hidden((Layer *)s_textlayer_date, true);
  }
  else {
    static char date[3];
    strftime(date, 3, "%d", t);
    text_layer_set_text(s_textlayer_date, date);
    
    #ifdef PBL_COLOR
      graphics_context_set_stroke_width(ctx, 2);
      if (strcmp(configs.dialcolor, "white") == 0 || strcmp(configs.dialcolor, "white_nl") == 0) {
        graphics_context_set_fill_color(ctx, GColorDarkGray);
        graphics_context_set_stroke_color(ctx, GColorDarkGray);
        text_layer_set_text_color(s_textlayer_date, GColorDarkGray);
      }
      else if (strcmp(configs.dialcolor, "black") == 0 || strcmp(configs.dialcolor, "black_nl") == 0) {
        graphics_context_set_fill_color(ctx, GColorWhite);
        graphics_context_set_stroke_color(ctx, GColorWhite);
        text_layer_set_text_color(s_textlayer_date, GColorWhite);
      };
    #else
      if (strcmp(configs.dialcolor, "white") == 0 || strcmp(configs.dialcolor, "white_nl") == 0) {
        graphics_context_set_fill_color(ctx, GColorBlack);
        graphics_context_set_stroke_color(ctx, GColorBlack);
        text_layer_set_text_color(s_textlayer_date, GColorBlack);
      }
      else if (strcmp(configs.dialcolor, "black") == 0 || strcmp(configs.dialcolor, "black_nl") == 0) {
        graphics_context_set_fill_color(ctx, GColorWhite);
        graphics_context_set_stroke_color(ctx, GColorWhite);
        text_layer_set_text_color(s_textlayer_date, GColorWhite);
      }
    #endif
    
    // Date box
    graphics_draw_rect(ctx, GRect(102, 74, 22, 20));
    layer_set_hidden((Layer *)s_textlayer_date, false);
  }
 
  #ifdef PBL_COLOR
      graphics_context_set_stroke_width(ctx, 1);
  #endif
  
  // Hour hand
  if (strcmp(configs.dialcolor, "white") == 0 || strcmp(configs.dialcolor, "white_nl") == 0) {
    graphics_context_set_fill_color(ctx, GColorBlack);
    graphics_context_set_stroke_color(ctx, GColorBlack);
  }
  else if (strcmp(configs.dialcolor, "black") == 0 || strcmp(configs.dialcolor, "black_nl") == 0) {
    graphics_context_set_fill_color(ctx, GColorWhite);
    graphics_context_set_stroke_color(ctx, GColorWhite);
  }

  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);
  gpath_draw_outline(ctx, s_hour_arrow);
  
  // Minute/hour hand
  if (strcmp(configs.dialcolor, "white") == 0 || strcmp(configs.dialcolor, "white_nl") == 0) {
    graphics_context_set_fill_color(ctx, GColorBlack);
    graphics_context_set_stroke_color(ctx, GColorBlack);
  }
  else if (strcmp(configs.dialcolor, "black") == 0 || strcmp(configs.dialcolor, "black_nl") == 0) {
    graphics_context_set_fill_color(ctx, GColorWhite);
    graphics_context_set_stroke_color(ctx, GColorWhite);
  }
  
  gpath_rotate_to(s_minute_arrow, TRIG_MAX_ANGLE * t->tm_min / 60);
  gpath_draw_filled(ctx, s_minute_arrow);
  gpath_draw_outline(ctx, s_minute_arrow);
  
  // Second hand
  if (strcmp(configs.secondhandoption, "quartz") == 0 || strcmp(configs.secondhandoption, "stop2go") == 0) {
    #ifdef PBL_COLOR
      graphics_context_set_fill_color(ctx, GColorRed);
      graphics_context_set_stroke_color(ctx, GColorRed);
    #else
      if (strcmp(configs.dialcolor, "white") == 0 || strcmp(configs.dialcolor, "white_nl") == 0) {
        graphics_context_set_fill_color(ctx, GColorBlack);
        graphics_context_set_stroke_color(ctx, GColorBlack);
      }
      else if (strcmp(configs.dialcolor, "black") == 0 || strcmp(configs.dialcolor, "black_nl") == 0) {
        graphics_context_set_fill_color(ctx, GColorWhite);
        graphics_context_set_stroke_color(ctx, GColorWhite);
      }
    #endif
      
    #ifdef PBL_COLOR
    graphics_context_set_stroke_width(ctx, 3);
    #endif
      
    //int16_t second_hand_length = (bounds.size.w / 2) - 22;
    int16_t second_hand_length = (bounds.size.w / 2) - 15;
    int16_t second_hand_opp_length = 16;
     
    double second_angle = 0;
    
    if (strcmp(configs.secondhandoption, "quartz") == 0) {
      second_angle = TRIG_MAX_ANGLE * t->tm_sec / 60;
    }
    // Stop2go
    else if (strcmp(configs.secondhandoption, "stop2go") == 0) {
      // Move the second hand around the watch in 58 seconds (60/58 = 1.03448275862)
      second_angle = TRIG_MAX_ANGLE * 1.03448275862 * (t->tm_sec / 60.0 + time_ms(NULL, NULL) / 60000.0);
      // Pause the second at 12 o'clock mark
      second_angle = (second_angle >= TRIG_MAX_ANGLE) ? TRIG_MAX_ANGLE : second_angle;
    }
    
    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 ,
    };
    
    graphics_draw_line(ctx, second_hand, center);
    
    GPoint second_hand_opp = {
      .x = (int16_t)(-sin_lookup(second_angle) * (int32_t)second_hand_opp_length / TRIG_MAX_RATIO) + center.x ,
      .y = (int16_t)(cos_lookup(second_angle) * (int32_t)second_hand_opp_length / TRIG_MAX_RATIO) + center.y ,
    };
    
    graphics_draw_line(ctx, second_hand_opp, center);
    
     // Second hand circle
    graphics_fill_circle(ctx, second_hand, 3);
    
    
    // Dot in the middle
    #ifdef PBL_COLOR
      graphics_context_set_fill_color(ctx, GColorRed);
      graphics_context_set_stroke_color(ctx, GColorRed);
    #else
      if (strcmp(configs.dialcolor, "white") == 0 || strcmp(configs.dialcolor, "white_nl") == 0) {
        graphics_context_set_fill_color(ctx, GColorBlack);
        graphics_context_set_stroke_color(ctx, GColorBlack);
      }
      else if (strcmp(configs.dialcolor, "black") == 0 || strcmp(configs.dialcolor, "black_nl") == 0) {
        graphics_context_set_fill_color(ctx, GColorWhite);
        graphics_context_set_stroke_color(ctx, GColorWhite);
      }
    #endif
    
    graphics_fill_circle(ctx, GPoint(bounds.size.w / 2,bounds.size.h / 2), 4);
  }
}

static void load_background_image() {
  gbitmap_destroy(s_background_bitmap);
  if (strcmp(configs.dialcolor, "white") == 0) {
    s_background_bitmap = gbitmap_create_with_resource(RESOURCE_ID_IMAGE_MONDAINE_WHITEBG);
  }
  else if (strcmp(configs.dialcolor, "white_nl") == 0) {
    s_background_bitmap = gbitmap_create_with_resource(RESOURCE_ID_IMAGE_MONDAINE_WHITENLBG);
  }
  else if (strcmp(configs.dialcolor, "black") == 0) {
    s_background_bitmap = gbitmap_create_with_resource(RESOURCE_ID_IMAGE_MONDAINE_BLACKBG);
  }
   else if (strcmp(configs.dialcolor, "black_nl") == 0) {
    s_background_bitmap = gbitmap_create_with_resource(RESOURCE_ID_IMAGE_MONDAINE_BLACKNLBG);
  }
  bitmap_layer_set_bitmap(s_background_layer, s_background_bitmap);
}
static void update_proc(Layer *layer, GContext *ctx) {
  int padding;
  
  PBL_IF_ROUND_ELSE(padding = 16, padding = 12);
  
  HOURS_TRACK_RADIUS = (window_bounds.size.w - padding) / 2; //66
  HOURS_TRACK_STROKE = 2;
  
  MINUTES_TRACK_RADIUS = HOURS_TRACK_RADIUS - 10; //56
  MINUTES_TRACK_STROKE = 2;
  
  SECONDS_TRACK_RADIUS = HOURS_TRACK_RADIUS - 20; //46
  SECONDS_TRACK_STROKE = 2;
  
  SECONDS_HAND_RADIUS = 2;
  MINUTES_HAND_RADIUS = 3;
  HOURS_HAND_RADIUS = 4;
  
  // Color background
  graphics_context_set_fill_color(ctx, GColorBlack);
  graphics_fill_rect(ctx, window_bounds, 0, GCornerNone);
  
  //APP_LOG(APP_LOG_LEVEL_DEBUG, "bounds: %d %d %d %d", window_bounds.origin.x, window_bounds.origin.y, window_bounds.size.h, window_bounds.size.w );
  

  //set colour for tracks
  graphics_context_set_stroke_color(ctx, GColorWhite );

  graphics_context_set_antialiased(ctx, ANTIALIASING);

  // Don't use current time while animating
  Time mode_time = s_last_time;
  
  // generate position of hands
  
  GPoint second_hand = (GPoint) {
    .x = (int16_t)(sin_lookup(TRIG_MAX_ANGLE * mode_time.seconds / 60) * (int32_t)(SECONDS_TRACK_RADIUS) / TRIG_MAX_RATIO) + s_center.x,
    .y = (int16_t)(-cos_lookup(TRIG_MAX_ANGLE * mode_time.seconds / 60) * (int32_t)(SECONDS_TRACK_RADIUS) / TRIG_MAX_RATIO) + s_center.y,
  };
	
  float minutes, hours;	
	
  if (SWEEP_MINUTES == true) {
	minutes = mode_time.minutes + (float)mode_time.seconds / 60;
  } else {
	minutes = mode_time.minutes;
  }
	
  GPoint minute_hand = (GPoint) {
    .x = (int16_t)(sin_lookup(TRIG_MAX_ANGLE * minutes / 60) * (int32_t)(MINUTES_TRACK_RADIUS) / TRIG_MAX_RATIO) + s_center.x,
    .y = (int16_t)(-cos_lookup(TRIG_MAX_ANGLE * minutes/ 60) * (int32_t)(MINUTES_TRACK_RADIUS) / TRIG_MAX_RATIO) + s_center.y,
  };

  if( SWEEP_HOURS == true) {
    hours = mode_time.hours + (float)mode_time.minutes / 60;
  } else {
	hours = mode_time.hours; 
  }

  GPoint hour_hand = (GPoint) {
    .x = (int16_t)(sin_lookup(TRIG_MAX_ANGLE * hours / 12) * (int32_t)(HOURS_TRACK_RADIUS) / TRIG_MAX_RATIO) + s_center.x,
    .y = (int16_t)(-cos_lookup(TRIG_MAX_ANGLE * hours / 12) * (int32_t)(HOURS_TRACK_RADIUS) / TRIG_MAX_RATIO) + s_center.y,
  };
	
  graphics_context_set_fill_color(ctx, GColorWhite);
  
  GRect seconds_rect = GRect(s_center.x - SECONDS_TRACK_RADIUS, s_center.y - SECONDS_TRACK_RADIUS, SECONDS_TRACK_RADIUS * 2, SECONDS_TRACK_RADIUS * 2);
  
  GRect minutes_rect = GRect(s_center.x - MINUTES_TRACK_RADIUS, s_center.y - MINUTES_TRACK_RADIUS, MINUTES_TRACK_RADIUS * 2, MINUTES_TRACK_RADIUS * 2);
  
  GRect hours_rect = GRect(s_center.x - HOURS_TRACK_RADIUS, s_center.y - HOURS_TRACK_RADIUS, HOURS_TRACK_RADIUS * 2, HOURS_TRACK_RADIUS * 2);
  
 //----------------------------------
    
  int seconds_start_angle, seconds_end_angle;
  
  int seconds_delta = 12;
  int minutes_delta = 12;
  int hours_delta = 12;
	
  get_angles_60(mode_time.seconds, 0, seconds_delta, &seconds_start_angle, &seconds_end_angle);
  
  //----------------------------------
  
  //int minutes_angle = mode_time.minutes * 360 / 60;
  int minutes_start_angle, minutes_end_angle;
    
  get_angles_60(mode_time.minutes, (SWEEP_MINUTES == true) ? mode_time.seconds : 0, minutes_delta, &minutes_start_angle, &minutes_end_angle);
  //get_angles_60(mode_time.minutes, mode_time.seconds, minutes_delta, &minutes_start_angle, &minutes_end_angle);
  
  //----------------------------------
  
  //int hours_angle = mode_time.hours * 360 / 12;
  int hours_start_angle, hours_end_angle;

  get_angles_12(mode_time.hours,(SWEEP_HOURS == true) ? mode_time.minutes : 0, hours_delta, &hours_start_angle, &hours_end_angle);
  
  //APP_LOG(APP_LOG_LEVEL_DEBUG, "seconds: %d, start: %d, end: %d",  mode_time.seconds, seconds_start_angle, seconds_end_angle);
  
   //set colour for arcs and "hands"
    graphics_context_set_fill_color(ctx, GColorWhite );
    
  //draw seconds arc
  graphics_fill_radial(ctx, seconds_rect, GOvalScaleModeFitCircle, SECONDS_TRACK_STROKE,  DEG_TO_TRIGANGLE(seconds_start_angle), DEG_TO_TRIGANGLE(seconds_end_angle));
  
  //draw minutes arc
  graphics_fill_radial(ctx, minutes_rect, GOvalScaleModeFitCircle, MINUTES_TRACK_STROKE,  DEG_TO_TRIGANGLE(minutes_start_angle), DEG_TO_TRIGANGLE(minutes_end_angle));
  
  //draw hours arc
  graphics_fill_radial(ctx, hours_rect, GOvalScaleModeFitCircle, HOURS_TRACK_STROKE,  DEG_TO_TRIGANGLE(hours_start_angle), DEG_TO_TRIGANGLE(hours_end_angle));
  
  //draw minute hand
  graphics_fill_circle(ctx, minute_hand, MINUTES_HAND_RADIUS);
  
  //draw hour hand
  graphics_fill_circle(ctx, hour_hand, HOURS_HAND_RADIUS);
  
  //draw second hand
  graphics_context_set_fill_color(ctx, GColorRed );
  graphics_fill_circle(ctx, second_hand, SECONDS_HAND_RADIUS);
	
	update_time();
}

static void window_load(Window *window) {
  Layer *window_layer = window_get_root_layer(window);
  
  window_bounds = layer_get_bounds(window_layer);
  
  //APP_LOG(APP_LOG_LEVEL_DEBUG, "bounds: %d %d %d %d", window_bounds.origin.x, window_bounds.origin.y, window_bounds.size.h, window_bounds.size.w );

  s_center = grect_center_point(&window_bounds);
  
  s_canvas_layer = layer_create(window_bounds);
  layer_set_update_proc(s_canvas_layer, update_proc);
  layer_add_child(window_layer, s_canvas_layer);
	
// Create time TextLayer
  
  int font_height;
  
  PBL_IF_ROUND_ELSE(font_height = 45, font_height = 36); //fudge factor to get text vertically centred
  
  s_time_layer = text_layer_create(GRect(window_bounds.origin.x, (window_bounds.size.h-font_height)/2, window_bounds.size.w, font_height));
	
  //s_center.y - MINUTES_TRACK_RADIUS + 18 + 18;
		
  s_day_layer = text_layer_create(GRect(0, s_center.y - 18 - 18  , window_bounds.size.w, 18)); //need to calculate proper y-location
  s_month_layer = text_layer_create(GRect(0, s_center.y +36 , window_bounds.size.w, 18)); //need to calculate proper y-location
  
  text_layer_set_background_color(s_day_layer, GColorRed);
  text_layer_set_text_color(s_day_layer, GColorLightGray  );
  text_layer_set_text(s_day_layer, "00");
  
  text_layer_set_background_color(s_time_layer, GColorClear);
  text_layer_set_text_color(s_time_layer, GColorWhite);
  text_layer_set_text(s_time_layer, "00:00");
	
  text_layer_set_background_color(s_month_layer, GColorClear);
  text_layer_set_text_color(s_month_layer, GColorLightGray );
  text_layer_set_text(s_month_layer, "XXX");
  
  PBL_IF_ROUND_ELSE(s_custom_font = fonts_load_custom_font(resource_get_handle(RESOURCE_ID_FONT_DOSIS_SEMIBOLD_40)), s_custom_font = fonts_load_custom_font(resource_get_handle(RESOURCE_ID_FONT_DOSIS_SEMIBOLD_30)));

  text_layer_set_font(s_time_layer, s_custom_font);
  text_layer_set_text_alignment(s_time_layer, GTextAlignmentCenter);
	
  text_layer_set_font(s_day_layer, fonts_load_custom_font(resource_get_handle(RESOURCE_ID_FONT_DOSIS_SEMIBOLD_18)));
  text_layer_set_text_alignment(s_day_layer, GTextAlignmentCenter);

  text_layer_set_font(s_month_layer, fonts_load_custom_font(resource_get_handle(RESOURCE_ID_FONT_DOSIS_SEMIBOLD_18)));
  text_layer_set_text_alignment(s_month_layer, GTextAlignmentCenter);
  
  // Add it as a child layer to the Window's root layer
  layer_add_child(window_get_root_layer(window), text_layer_get_layer(s_time_layer));
  layer_add_child(window_get_root_layer(window), text_layer_get_layer(s_day_layer));
  layer_add_child(window_get_root_layer(window), text_layer_get_layer(s_month_layer));
	// Make sure the time is displayed from the start
  update_time();
}

static void window_unload(Window *window) {
  layer_destroy(s_canvas_layer);
  // Destroy TextLayer
  text_layer_destroy(s_time_layer);
  text_layer_destroy(s_day_layer);
  text_layer_destroy(s_month_layer);
  fonts_unload_custom_font(s_custom_font);
}

/*********************************** App **************************************/

static void init() {
  srand(time(NULL));

  time_t t = time(NULL);
  struct tm *time_now = localtime(&t);
  tick_handler(time_now, SECOND_UNIT);

  s_main_window = window_create();
  window_set_window_handlers(s_main_window, (WindowHandlers) {
    .load = window_load,
    .unload = window_unload,
  });
Пример #9
0
static void hands_layer_update_proc (Layer* layer, GContext* ctx) {
  GRect rect = layer_get_frame(layer);
  GPoint center = grect_center_point(&rect);
  GPath second_hand_path;
  GPath minute_hand_path;
  GPath hour_hand_path;
  PblTm time;
  char day_text[] = "  ";
  char month_text[] = "   ";
  char month_format[] = "%b";
  int32_t second_angle;
  int32_t minute_angle;
  int32_t hour_angle;
  
  int32_t trig_ninety = TRIG_MAX_ANGLE / 4;
  int32_t trig_one_eighty = TRIG_MAX_ANGLE / 2;

  int32_t trig_second_angle;
  float second_length;

  int32_t trig_minute_angle;
  float minute_length = 60;

  int32_t trig_hour_angle;
  float hour_length = 60;

  get_time(&time);

  if (time.tm_hour > 12) {
    time.tm_hour-=12;
}

  second_angle = time.tm_sec * 6;
  minute_angle = time.tm_min * 6;
  hour_angle = (time.tm_hour * 30) + (time.tm_min / 2);

  trig_second_angle = (TRIG_MAX_ANGLE / 60) * time.tm_sec;
  trig_minute_angle = (TRIG_MAX_ANGLE / 60) * time.tm_min;
  trig_hour_angle = (TRIG_MAX_ANGLE / 360) * hour_angle;

  if (((time.tm_sec >= 7 && time.tm_sec <= 23) ||
       (time.tm_sec >= 37 && time.tm_sec <= 53)) &&
      time.tm_sec != 0) {
    second_length = (72 * TRIG_MAX_ANGLE) / (cos_lookup(trig_second_angle - trig_ninety));
    second_hand_path_points.points[4].y = (second_length > 0) ? -(second_length) : second_length;
    second_hand_path_points.points[3].y = (second_length > 0) ? -(second_length-5) : second_length+5;
    second_hand_path_points.points[5].y = (second_length > 0) ? -(second_length-5) : second_length+5;
  }
  else {
    second_length = (84 * TRIG_MAX_ANGLE) / (cos_lookup(trig_second_angle - trig_one_eighty));
    second_hand_path_points.points[4].y = (second_length > 0) ? -(second_length) : second_length;
    second_hand_path_points.points[3].y = (second_length > 0) ? -(second_length-5) : second_length+5;
    second_hand_path_points.points[5].y = (second_length > 0) ? -(second_length-5) : second_length+5;
  }

  if (((time.tm_min >= 7 && time.tm_min <= 23) ||
       (time.tm_min >= 37 && time.tm_min <= 53)) &&
      time.tm_min != 0) {
    minute_length = (72 * TRIG_MAX_ANGLE) / (cos_lookup(trig_minute_angle - trig_ninety));
    minute_hand_path_points.points[4].y = (minute_length > 0) ? -(minute_length) : minute_length;
    minute_hand_path_points.points[3].y = (minute_length > 0) ? -(minute_length-5) : minute_length+5;
    minute_hand_path_points.points[5].y = (minute_length > 0) ? -(minute_length-5) : minute_length+5;
  }
  else {
    minute_length = (84 * TRIG_MAX_ANGLE) / (cos_lookup(trig_minute_angle - trig_one_eighty));
    minute_hand_path_points.points[4].y = (minute_length > 0) ? -(minute_length) : minute_length;
    minute_hand_path_points.points[3].y = (minute_length > 0) ? -(minute_length-5) : minute_length+5;
    minute_hand_path_points.points[5].y = (minute_length > 0) ? -(minute_length-5) : minute_length+5;
  }

  // the number of pixels the hour hand will remain from the window edge
  int hour_length_offset = 35;

  if (((hour_angle >= 49 && hour_angle <= 139) ||
       (hour_angle >= 229 && hour_angle <= 311)) &&
      hour_angle != 0) {
    hour_length = (72 * TRIG_MAX_ANGLE) / (cos_lookup(trig_hour_angle - trig_ninety));
    hour_hand_path_points.points[4].y = (hour_length > 0) ? -(hour_length-hour_length_offset) : hour_length+hour_length_offset;
    hour_hand_path_points.points[3].y = (hour_length > 0) ? -(hour_length-(hour_length_offset+5)) : hour_length+(hour_length_offset+5);
    hour_hand_path_points.points[5].y = (hour_length > 0) ? -(hour_length-(hour_length_offset+5)) : hour_length+(hour_length_offset+5);
  }
  else {
    hour_length = (84 * TRIG_MAX_ANGLE) / (cos_lookup(trig_hour_angle - trig_one_eighty));
    hour_hand_path_points.points[4].y = (hour_length > 0) ? -(hour_length-hour_length_offset) : hour_length+hour_length_offset;
    hour_hand_path_points.points[3].y = (hour_length > 0) ? -(hour_length-(hour_length_offset + 5)) : hour_length+(hour_length_offset + 5);
    hour_hand_path_points.points[5].y = (hour_length > 0) ? -(hour_length-(hour_length_offset + 5)) : hour_length+(hour_length_offset + 5);
  }

  gpath_init(&minute_hand_path, &minute_hand_path_points);
  gpath_move_to(&minute_hand_path, center);
  gpath_rotate_to(&minute_hand_path, TRIG_MAX_ANGLE / 360 * minute_angle);
  graphics_context_set_fill_color(ctx, GColorWhite);
  graphics_context_set_stroke_color(ctx, GColorBlack);
  gpath_draw_filled(ctx, &minute_hand_path);
  gpath_draw_outline(ctx, &minute_hand_path);

  gpath_init(&hour_hand_path, &hour_hand_path_points);
  gpath_move_to(&hour_hand_path, center);
  gpath_rotate_to(&hour_hand_path, TRIG_MAX_ANGLE / 360 * hour_angle);
  graphics_context_set_fill_color(ctx, GColorWhite);
  graphics_context_set_stroke_color(ctx, GColorBlack);
  gpath_draw_filled(ctx, &hour_hand_path);
  gpath_draw_outline(ctx, &hour_hand_path);

  gpath_init(&second_hand_path, &second_hand_path_points);
  gpath_move_to(&second_hand_path, center);
  gpath_rotate_to(&second_hand_path, TRIG_MAX_ANGLE / 360 * second_angle);
  graphics_context_set_fill_color(ctx, GColorBlack);
  graphics_context_set_stroke_color(ctx, GColorWhite);
  gpath_draw_filled(ctx, &second_hand_path);
  gpath_draw_outline(ctx, &second_hand_path);

  /* graphics_context_set_fill_color(ctx, GColorWhite); */
  /* graphics_context_set_stroke_color(ctx, GColorBlack); */
  /* graphics_fill_circle(ctx, center, 7); */
  /* //  graphics_draw_circle(ctx, center, 8); */

  /* strcpy(day_text, itoa(time.tm_mday)); */
  /* draw_outlined_text(ctx, */
  /* 		     day_text, */
  /* 		     fonts_get_system_font(FONT_KEY_GOTHIC_14_BOLD), */
  /* 		     GRect(0,75,144,168-80), */
  /* 		     GTextOverflowModeWordWrap, */
  /* 		     GTextAlignmentCenter, */
  /* 		     1, */
  /* 		     false); */
}
Пример #10
0
void moon_LayerUpdateProc(struct Layer *layer, GContext *ctx) {
/*
	GPath shadow;
	GPathInfo shadow_points = {
		5,
		(GPoint []) {
			{0, 0},
			{0, 0},
			{0, 0},
			{0, 0},
			{0, 0},
		}
	};
*/
	int radius;
	int x, y, error;
	int mx, my;
	GPoint center;
	int edge;

	if(phase == 1) {
		graphics_context_set_fill_color(ctx, GColorBlack);
		graphics_fill_rect(ctx, GRect(0, 0, layer->frame.size.w, layer->frame.size.h), 0, GCornerNone);
		return;
	}
	if(phase == 15)
		return;
	graphics_context_set_fill_color(ctx, GColorWhite);
	center.x = layer->frame.size.w / 2;
	center.y = layer->frame.size.h / 2;
	radius = (layer->frame.size.w > layer->frame.size.h ?
		layer->frame.size.h / 2 :
		layer->frame.size.w / 2) - 4;
//	graphics_fill_circle(ctx, center, radius);

	graphics_context_set_stroke_color(ctx, GColorBlack);
	// circle algo from: http://en.wikipedia.org/wiki/Midpoint_circle_algorithm
	// Even though I studied it in school, it still feels like magic
	error = -radius;
	x = radius;
	y = 0;
	while ( x >= y) {
		if(phase < 15) {
			mx = x * (cos_lookup(TRIG_MAX_ANGLE * (phase / 28.0)) / (0xffff * 1.0));
			my = y * (cos_lookup(TRIG_MAX_ANGLE * (phase / 28.0)) / (0xffff * 1.0));
			edge = 0;
		}
		if(phase > 15) {
			mx = x * (cos_lookup(TRIG_MAX_ANGLE * ((phase - 15) / 32.0)) / (0xffff * 1.0));
			my = y * (cos_lookup(TRIG_MAX_ANGLE * ((phase - 15) / 32.0)) / (0xffff * 1.0));
			edge = layer->frame.size.w;
		}
		graphics_draw_line(ctx, GPoint(center.x + mx, center.y + y), GPoint(edge, center.y + y));
		graphics_draw_line(ctx, GPoint(center.x + mx, center.y - y), GPoint(edge, center.y - y));
		graphics_draw_line(ctx, GPoint(center.x + my, center.y + x), GPoint(edge, center.y + x));
		graphics_draw_line(ctx, GPoint(center.x + my, center.y - x), GPoint(edge, center.y - x));

		error += y;
		++y;
		error += y;
		if( error >= 0) {
			error -= x;
			--x;
			error -= x;
		}
	}
}
Пример #11
0
static void gpath_draw_filled_custom(GContext* ctx, GPath *path, GColor8 fill_color){
	if(path->num_points == 0)
		return;	

	GPoint offset = path->offset;
	int32_t rotation = path->rotation;

	int32_t s = sin_lookup(rotation);
  	int32_t c = cos_lookup(rotation);

  	// Rotate each point of the gpath and memorize the min/max
	GPoint* points_rot = malloc(sizeof(GPoint) * path->num_points);
	GPoint top_right = (GPoint){(1 << 15)-1,(1 << 15)-1};
	GPoint bottom_left= (GPoint){-(1 << 15),-(1 << 15)};

  	for(uint32_t i=0; i<path->num_points; i++){
  		points_rot[i].x = (path->points[i].x * c - path->points[i].y * s) / TRIG_MAX_RATIO  + offset.x;
		points_rot[i].y = (path->points[i].x * s + path->points[i].y * c) / TRIG_MAX_RATIO  + offset.y;
		if(points_rot[i].x > bottom_left.x)
			bottom_left.x = points_rot[i].x;
		if(points_rot[i].x < top_right.x)
			top_right.x = points_rot[i].x;
		if(points_rot[i].y > bottom_left.y)
			bottom_left.y = points_rot[i].y;
		if(points_rot[i].y < top_right.y)
			top_right.y = points_rot[i].y;
  	}

  	// Create an array bitmap pebble v2 style (1 bit equals 1 pixel)
  	int32_t bytes_per_row = (bottom_left.x - top_right.x + 1) / 8 + ((bottom_left.x - top_right.x  + 1) % 8 == 0 ? 0 : 1);
  	int32_t h = bottom_left.y - top_right.y + 1;
  	uint8_t* pixels = malloc(bytes_per_row * h);
  	memset(pixels, 0, bytes_per_row * h);

  	// And draw the outline path in this 1 bit image
  	GPoint prev_p = points_rot[path->num_points - 1];
  	GPoint p;
  	for(uint32_t i=0; i<path->num_points; i++){
  		p = points_rot[i];
  		bmpDrawLine(pixels, bytes_per_row, prev_p.x - top_right.x, prev_p.y - top_right.y, p.x - top_right.x, p.y - top_right.y);
  		prev_p = p;
  	}

  	free(points_rot);

  	// Compute the starting point for the flow fill algorithm 
  	// TODO tobe improved
  	GPoint start;
  	start.x = (points_rot[0].x + points_rot[1].x) / 2;
  	start.y = (points_rot[0].y + points_rot[1].y) / 2;

  	if(points_rot[0].x < points_rot[1].x){
  		if(points_rot[0].y < points_rot[1].y){
  			start.x--;
  			start.y++;
  		}
  		else {
  			start.x++;
  			start.y++;
  		}
  	}
  	else {
  		if(points_rot[0].y < points_rot[1].y){
  			start.x--;
  			start.y--;
  		}
  		else {
  			start.x++;
  			start.y--;
  		}
  	}

  	// Capture the frame buffer
  	GBitmap* bitmap = graphics_capture_frame_buffer(ctx);

  	// flood fill the gpath
  	floodFill(bitmap, pixels, bytes_per_row, start, top_right, fill_color);

  	// Release the frame buffer
  	graphics_release_frame_buffer(ctx, bitmap);  	

  	//Release the working variables
  	free(pixels);
}
Пример #12
0
static void draw_proc(Layer *layer, GContext *ctx) {
  srand(time(NULL));  // For screenshots
  GRect bounds = layer_get_bounds(layer);
  GPoint center = grect_center_point(&bounds);
  
  int lastMin = 0;
  if (SCREENSHOT_RUN) {
    lastMin = s_last_time.seconds;  // For screenshots
  } else {
    lastMin = s_last_time.minutes;  // For real
  }

  for (int m = 0; m <= 59; m++) {
    if (m <= lastMin) {
      graphics_context_set_fill_color(ctx, getDotMainColor());
    } else {
      graphics_context_set_fill_color(ctx, getDotDarkColor());
    }
    
    int v = DOT_DISTANCE;
    
    int numDots = s_dotArray[m];
    
    if (m == lastMin || SCREENSHOT_RUN) {
      numDots = getNumDots();
      s_dotArray[m] = numDots;
    } else if (numDots == 0 && m <= lastMin) {
      numDots = 1;
    }

    // For each dot
    for (int i = 0; i < numDots; i++) {

      // Draw dot
      for(int y = 0; y < 1; y++) {
        for(int x = 0; x < 1; x++) {
          GPoint point = (GPoint) {
            .x = (int16_t)(sin_lookup(TRIG_MAX_ANGLE * m / 60) * (int32_t)(v) / TRIG_MAX_RATIO) + center.x,
            .y = (int16_t)(-cos_lookup(TRIG_MAX_ANGLE * m / 60) * (int32_t)(v) / TRIG_MAX_RATIO) + center.y,
          };
          graphics_fill_circle(ctx, GPoint(point.x + x, point.y + y), s_dotSize);
        }
      }
      
      // Draw next dot farther away
      v += DOT_SPACING;
    }
  }
  
  if (config_get(PERSIST_KEY_WEATHER) && hasWeather) {
    // Get weather "minute"
    int m = weatherTemp % 60;
    
    // Get weather dot color
    if (weatherTemp < 0) {
      graphics_context_set_fill_color(ctx, GColorCeleste);
    } else if (weatherTemp < 60) {
      graphics_context_set_fill_color(ctx, GColorMediumAquamarine);
    } else {
      graphics_context_set_fill_color(ctx, GColorOrange);
    }
    
    // Draw dot
    int v = DOT_DISTANCE - DOT_SPACING - 1;
    for(int y = 0; y < 1; y++) {
      for(int x = 0; x < 1; x++) {
        GPoint point = (GPoint) {
          .x = (int16_t)(sin_lookup(TRIG_MAX_ANGLE * m / 60) * (int32_t)(v) / TRIG_MAX_RATIO) + center.x,
          .y = (int16_t)(-cos_lookup(TRIG_MAX_ANGLE * m / 60) * (int32_t)(v) / TRIG_MAX_RATIO) + center.y,
        };
        graphics_fill_circle(ctx, GPoint(point.x + x, point.y + y), s_dotSize);
      }
    }
  }
}

static void health_handler(HealthEventType event, void *context) {
  // Which type of event occured?
  switch(event) {
    case HealthEventSignificantUpdate:
//       APP_LOG(APP_LOG_LEVEL_INFO, "New HealthService HealthEventSignificantUpdate event");
      break;
    case HealthEventMovementUpdate:
      APP_LOG(APP_LOG_LEVEL_INFO, "New HealthService HealthEventMovementUpdate event");
    
      // Mark layer dirty so it updates
      layer_mark_dirty(s_canvas_layer);
      break;
    case HealthEventSleepUpdate:
//       APP_LOG(APP_LOG_LEVEL_INFO, "New HealthService HealthEventSleepUpdate event");
      break;
  }
}

void comm_init() {
  app_message_register_inbox_received(in_recv_handler);
  
  // Register callbacks
  app_message_register_inbox_dropped(inbox_dropped_callback);
  app_message_register_outbox_failed(outbox_failed_callback);
  app_message_register_outbox_sent(outbox_sent_callback);
  
  app_message_open(app_message_inbox_size_maximum(), app_message_outbox_size_maximum());
}