// Draws the frame and optionally fills the background of the current date window. void draw_date_window_background(GContext *ctx, unsigned int fg_draw_mode, unsigned int bg_draw_mode, bool opaque_layer) { if (opaque_layer || bg_draw_mode != fg_draw_mode) { if (date_window_mask.bitmap == NULL) { date_window_mask = rle_bwd_create(RESOURCE_ID_DATE_WINDOW_MASK); if (date_window_mask.bitmap == NULL) { trigger_memory_panic(__LINE__); return; } } graphics_context_set_compositing_mode(ctx, draw_mode_table[bg_draw_mode].paint_mask); graphics_draw_bitmap_in_rect(ctx, date_window_mask.bitmap, date_window_box); } if (date_window.bitmap == NULL) { date_window = rle_bwd_create(RESOURCE_ID_DATE_WINDOW); if (date_window.bitmap == NULL) { bwd_destroy(&date_window_mask); trigger_memory_panic(__LINE__); return; } } graphics_context_set_compositing_mode(ctx, draw_mode_table[fg_draw_mode].paint_fg); graphics_draw_bitmap_in_rect(ctx, date_window.bitmap, date_window_box); }
void draw_chrono_dial(GContext *ctx) { // app_log(APP_LOG_LEVEL_INFO, __FILE__, __LINE__, "draw_chrono_dial"); if (config.chrono_dial != CDM_off) { #ifdef PBL_PLATFORM_APLITE BitmapWithData chrono_dial_black; if (chrono_dial_shows_tenths) { chrono_dial_black = rle_bwd_create(RESOURCE_ID_CHRONO_DIAL_TENTHS_BLACK); } else { chrono_dial_black = rle_bwd_create(RESOURCE_ID_CHRONO_DIAL_HOURS_BLACK); } if (chrono_dial_black.bitmap == NULL) { bwd_destroy(&chrono_dial_black); trigger_memory_panic(__LINE__); } #endif // PBL_PLATFORM_APLITE // In Basalt, we only load the "white" image. if (chrono_dial_white.bitmap == NULL) { if (chrono_dial_shows_tenths) { chrono_dial_white = rle_bwd_create(RESOURCE_ID_CHRONO_DIAL_TENTHS_WHITE); } else { chrono_dial_white = rle_bwd_create(RESOURCE_ID_CHRONO_DIAL_HOURS_WHITE); } if (chrono_dial_white.bitmap == NULL) { trigger_memory_panic(__LINE__); return; } // We apply the color scheme as needed. remap_colors_clock(&chrono_dial_white); } int x = chrono_tenth_hand_def.place_x - chrono_dial_size.w / 2; int y = chrono_tenth_hand_def.place_y - chrono_dial_size.h / 2; GRect destination = GRect(x, y, chrono_dial_size.w, chrono_dial_size.h); #ifdef PBL_PLATFORM_APLITE graphics_context_set_compositing_mode(ctx, draw_mode_table[config.draw_mode ^ APLITE_INVERT].paint_fg); graphics_draw_bitmap_in_rect(ctx, chrono_dial_black.bitmap, destination); graphics_context_set_compositing_mode(ctx, draw_mode_table[config.draw_mode ^ APLITE_INVERT].paint_bg); graphics_draw_bitmap_in_rect(ctx, chrono_dial_white.bitmap, destination); #else // PBL_PLATFORM_APLITE graphics_context_set_compositing_mode(ctx, GCompOpSet); graphics_draw_bitmap_in_rect(ctx, chrono_dial_white.bitmap, destination); #endif // PBL_PLATFORM_APLITE if (!keep_assets) { bwd_destroy(&chrono_dial_white); } #ifdef PBL_PLATFORM_APLITE bwd_destroy(&chrono_dial_black); #endif // PBL_PLATFORM_APLITE } }
// Draws a date window with the current lunar phase. void draw_lunar_window(Layer *me, GContext *ctx, DateWindowMode dwm, bool invert, bool opaque_layer) { // The draw_mode is the color to draw the frame of the date window. unsigned int draw_mode = invert ^ config.draw_mode; // The moon_draw_mode is the color to draw the moon within the date window. unsigned int moon_draw_mode = draw_mode; if (config.lunar_background) { // If the user specified an always-black background, that means moon_draw_mode is always 1. moon_draw_mode = 1; } draw_date_window_background(ctx, draw_mode, moon_draw_mode, opaque_layer); if (moon_bitmap.bitmap == NULL) { assert(current_placement.lunar_phase <= 7); if (moon_draw_mode == 0) { moon_bitmap = rle_bwd_create(RESOURCE_ID_MOON_BLACK_0 + current_placement.lunar_phase); } else { moon_bitmap = rle_bwd_create(RESOURCE_ID_MOON_WHITE_0 + current_placement.lunar_phase); } if (moon_bitmap.bitmap == NULL) { trigger_memory_panic(__LINE__); return; } if (config.lunar_direction) { // Draw the moon phases animating from left-to-right, as seen in // the southern hemisphere. (This really means drawing the moon // upside-down, as it would be seen by someone facing north.) flip_bitmap_x(moon_bitmap.bitmap, NULL); flip_bitmap_y(moon_bitmap.bitmap, NULL); } } // Draw the moon in the fg color. This will be black-on-white if // moon_draw_mode = 0, or white-on-black if moon_draw_mode = 1. // Since we have selected the particular moon resource above based // on draw_mode, we will always draw the moon in the correct color, // so that it looks like the moon. (Drawing the moon in the // inverted color would look weird.) graphics_context_set_compositing_mode(ctx, draw_mode_table[moon_draw_mode].paint_black); if (config.lunar_direction) { graphics_draw_bitmap_in_rect(ctx, moon_bitmap.bitmap, date_window_box_offset); } else { graphics_draw_bitmap_in_rect(ctx, moon_bitmap.bitmap, date_window_box); } }
void clock_face_layer_update_callback(Layer *me, GContext *ctx) { // app_log(APP_LOG_LEVEL_INFO, __FILE__, __LINE__, "clock_face_layer"); if (memory_panic_count > 5) { // In case we're in extreme memory panic mode--too little // available memory to even keep the clock face resident--we do // nothing in this function. return; } // Load the clock face from the resource file if we haven't already. if (clock_face.bitmap == NULL) { clock_face = rle_bwd_create(clock_face_table[config.face_index]); if (clock_face.bitmap == NULL) { trigger_memory_panic(__LINE__); return; } } // Draw the clock face into the layer. GRect destination = layer_get_bounds(me); destination.origin.x = 0; destination.origin.y = 0; graphics_context_set_compositing_mode(ctx, draw_mode_table[config.draw_mode].paint_assign); graphics_draw_bitmap_in_rect(ctx, clock_face.bitmap, destination); }
void load_chrono_dial() { #ifdef PBL_PLATFORM_APLITE bwd_destroy(&chrono_dial_white); bwd_destroy(&chrono_dial_black); if (chrono_dial_shows_tenths) { chrono_dial_white = rle_bwd_create(RESOURCE_ID_CHRONO_DIAL_TENTHS_WHITE); chrono_dial_black = rle_bwd_create(RESOURCE_ID_CHRONO_DIAL_TENTHS_BLACK); } else { chrono_dial_white = rle_bwd_create(RESOURCE_ID_CHRONO_DIAL_HOURS_WHITE); chrono_dial_black = rle_bwd_create(RESOURCE_ID_CHRONO_DIAL_HOURS_BLACK); } if (chrono_dial_white.bitmap == NULL || chrono_dial_black.bitmap == NULL) { bwd_destroy(&chrono_dial_white); bwd_destroy(&chrono_dial_black); trigger_memory_panic(__LINE__); } #else // PBL_PLATFORM_APLITE // In Basalt, we only load the "white" image. bwd_destroy(&chrono_dial_white); if (chrono_dial_shows_tenths) { chrono_dial_white = rle_bwd_create(RESOURCE_ID_CHRONO_DIAL_TENTHS_WHITE); } else { chrono_dial_white = rle_bwd_create(RESOURCE_ID_CHRONO_DIAL_HOURS_WHITE); } if (chrono_dial_white.bitmap == NULL) { bwd_destroy(&chrono_dial_white); trigger_memory_panic(__LINE__); return; } // We apply the color-inverting mode if necessary. uint8_t xor_argb8 = config.draw_mode ? 0x3f : 0x00; bwd_adjust_colors(&chrono_dial_white, 0xff, 0x00, xor_argb8); #endif // PBL_PLATFORM_APLITE }
void draw_bluetooth_indicator(GContext *ctx, int x, int y, bool invert) { if (config.bluetooth_indicator == IM_off) { return; } GRect box; box.origin.x = x; box.origin.y = y; box.size.w = BLUETOOTH_SIZE_X; box.size.h = BLUETOOTH_SIZE_Y; GCompOp fg_mode; #ifdef PBL_BW GCompOp mask_mode; if (invert ^ config.draw_mode ^ BW_INVERT) { fg_mode = GCompOpSet; mask_mode = GCompOpAnd; } else { fg_mode = GCompOpAnd; mask_mode = GCompOpSet; } #else // PBL_BW // In Basalt, we always use GCompOpSet because the icon includes its // own alpha channel. fg_mode = GCompOpSet; #endif // PBL_BW (void)poll_quiet_time_state(); // Just in case it's recently changed. if (!got_bluetooth_state) { bluetooth_state = bluetooth_connection_service_peek(); got_bluetooth_state = true; } if (bluetooth_state != bluetooth_buzzed_state) { bluetooth_buzzed_state = bluetooth_state; if (config.bluetooth_buzzer && !bluetooth_buzzed_state) { // We just lost the bluetooth connection. Ring the buzzer, if // it isn't quiet time. if (!quiet_time_state) { vibes_short_pulse(); } } } if (bluetooth_buzzed_state) { // Bluetooth is connected. if (quiet_time_state) { // If bluetooth is connected and quiet time is enabled, we draw // the "quiet time" bitmap. #ifndef PBL_PLATFORM_APLITE #ifdef PBL_BW if (quiet_time_mask.bitmap == NULL) { quiet_time_mask = rle_bwd_create(RESOURCE_ID_QUIET_TIME_MASK); } graphics_context_set_compositing_mode(ctx, mask_mode); graphics_draw_bitmap_in_rect(ctx, quiet_time_mask.bitmap, box); #endif // PBL_BW if (quiet_time.bitmap == NULL) { quiet_time = rle_bwd_create(RESOURCE_ID_QUIET_TIME); } graphics_context_set_compositing_mode(ctx, fg_mode); graphics_draw_bitmap_in_rect(ctx, quiet_time.bitmap, box); #endif // PBL_PLATFORM_APLITE } else { // If bluetooth is connected and quiet time is not enabled, we // draw the "connected" bitmap, unless bluetooth_indicator is // set to IM_when_needed. if (config.bluetooth_indicator != IM_when_needed) { #ifdef PBL_BW if (bluetooth_mask.bitmap == NULL) { bluetooth_mask = rle_bwd_create(RESOURCE_ID_BLUETOOTH_MASK); } graphics_context_set_compositing_mode(ctx, mask_mode); graphics_draw_bitmap_in_rect(ctx, bluetooth_mask.bitmap, box); #endif // PBL_BW if (bluetooth_connected.bitmap == NULL) { bluetooth_connected = rle_bwd_create(RESOURCE_ID_BLUETOOTH_CONNECTED); } graphics_context_set_compositing_mode(ctx, fg_mode); graphics_draw_bitmap_in_rect(ctx, bluetooth_connected.bitmap, box); } } } else { // If bluetooth is disconnected, we draw the "disconnected" bitmap // (except in the IM_off case, of course). #ifdef PBL_BW if (bluetooth_mask.bitmap == NULL) { bluetooth_mask = rle_bwd_create(RESOURCE_ID_BLUETOOTH_MASK); } graphics_context_set_compositing_mode(ctx, mask_mode); graphics_draw_bitmap_in_rect(ctx, bluetooth_mask.bitmap, box); #endif // PBL_BW if (bluetooth_disconnected.bitmap == NULL) { bluetooth_disconnected = rle_bwd_create(RESOURCE_ID_BLUETOOTH_DISCONNECTED); } graphics_context_set_compositing_mode(ctx, fg_mode); graphics_draw_bitmap_in_rect(ctx, bluetooth_disconnected.bitmap, box); } if (!keep_assets) { destroy_bluetooth_bitmaps(); } }
// Draws a given hand on the face, using the bitmap structures. void draw_bitmap_hand(struct HandCache *hand_cache, struct HandDef *hand_def, int hand_index, GContext *ctx) { if (hand_cache->bitmap_hand_index != hand_index) { // Force a new bitmap. if (hand_cache->image.bitmap != NULL) { bwd_destroy(&hand_cache->image); } if (hand_cache->mask.bitmap != NULL) { bwd_destroy(&hand_cache->mask); } hand_cache->bitmap_hand_index = hand_index; } struct BitmapHandTableRow *hand = &hand_def->bitmap_table[hand_index]; int bitmap_index = hand->bitmap_index; struct BitmapHandCenterRow *lookup = &hand_def->bitmap_centers[bitmap_index]; int hand_resource_id = hand_def->resource_id + bitmap_index; int hand_resource_mask_id = hand_def->resource_mask_id + bitmap_index; if (hand_def->resource_id == hand_def->resource_mask_id) { // The hand does not have a mask. Draw the hand on top of the scene. if (hand_cache->image.bitmap == NULL) { if (hand_def->use_rle) { hand_cache->image = rle_bwd_create(hand_resource_id); } else { hand_cache->image = png_bwd_create(hand_resource_id); } if (hand_cache->image.bitmap == NULL) { hand_cache_destroy(hand_cache); trigger_memory_panic(__LINE__); return; } hand_cache->cx = lookup->cx; hand_cache->cy = lookup->cy; if (hand->flip_x) { // To minimize wasteful resource usage, if the hand is symmetric // we can store only the bitmaps for the right half of the clock // face, and flip them for the left half. flip_bitmap_x(hand_cache->image.bitmap, &hand_cache->cx); } if (hand->flip_y) { // We can also do this vertically. flip_bitmap_y(hand_cache->image.bitmap, &hand_cache->cy); } } // We make sure the dimensions of the GRect to draw into // are equal to the size of the bitmap--otherwise the image // will automatically tile. GRect destination = hand_cache->image.bitmap->bounds; // Place the hand's center point at place_x, place_y. destination.origin.x = hand_def->place_x - hand_cache->cx; destination.origin.y = hand_def->place_y - hand_cache->cy; // Specify a compositing mode to make the hands overlay on top of // each other, instead of the background parts of the bitmaps // blocking each other. if (hand_def->paint_black) { // Painting foreground ("white") pixels as black. graphics_context_set_compositing_mode(ctx, draw_mode_table[config.draw_mode].paint_black); } else { // Painting foreground ("white") pixels as white. graphics_context_set_compositing_mode(ctx, draw_mode_table[config.draw_mode].paint_white); } graphics_draw_bitmap_in_rect(ctx, hand_cache->image.bitmap, destination); } else { // The hand has a mask, so use it to draw the hand opaquely. if (hand_cache->image.bitmap == NULL) { if (hand_def->use_rle) { hand_cache->image = rle_bwd_create(hand_resource_id); hand_cache->mask = rle_bwd_create(hand_resource_mask_id); } else { hand_cache->image = png_bwd_create(hand_resource_id); hand_cache->mask = png_bwd_create(hand_resource_mask_id); } if (hand_cache->image.bitmap == NULL || hand_cache->mask.bitmap == NULL) { hand_cache_destroy(hand_cache); trigger_memory_panic(__LINE__); return; } hand_cache->cx = lookup->cx; hand_cache->cy = lookup->cy; if (hand->flip_x) { // To minimize wasteful resource usage, if the hand is symmetric // we can store only the bitmaps for the right half of the clock // face, and flip them for the left half. flip_bitmap_x(hand_cache->image.bitmap, &hand_cache->cx); flip_bitmap_x(hand_cache->mask.bitmap, NULL); } if (hand->flip_y) { // We can also do this vertically. flip_bitmap_y(hand_cache->image.bitmap, &hand_cache->cy); flip_bitmap_y(hand_cache->mask.bitmap, NULL); } } GRect destination = hand_cache->image.bitmap->bounds; destination.origin.x = hand_def->place_x - hand_cache->cx; destination.origin.y = hand_def->place_y - hand_cache->cy; graphics_context_set_compositing_mode(ctx, draw_mode_table[config.draw_mode].paint_white); graphics_draw_bitmap_in_rect(ctx, hand_cache->mask.bitmap, destination); graphics_context_set_compositing_mode(ctx, draw_mode_table[config.draw_mode].paint_black); graphics_draw_bitmap_in_rect(ctx, hand_cache->image.bitmap, destination); } }