// 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); } }
// Draws a given hand on the face, using the bitmap structures. void draw_bitmap_hand(struct BitmapHandTableRow *hand, int place_x, int place_y, GContext *ctx) { int cx, cy; cx = hand->cx; cy = hand->cy; if (hand->mask_id == hand->image_id) { // The hand does not have a mask. Draw the hand on top of the scene. BmpContainer image; bmp_init_container(hand->image_id, &image); 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(&image, &cx); } if (hand->flip_y) { // We can also do this vertically. flip_bitmap_y(&image, &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 = layer_get_frame(&image.layer.layer); // Place the hand's center point at place_x, place_y. destination.origin.x = place_x - cx; destination.origin.y = place_y - 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->paint_black) { // Painting foreground ("white") pixels as black. graphics_context_set_compositing_mode(ctx, GCompOpClear); } else { // Painting foreground ("white") pixels as white. graphics_context_set_compositing_mode(ctx, GCompOpOr); } graphics_draw_bitmap_in_rect(ctx, &image.bmp, destination); bmp_deinit_container(&image); } else { // The hand has a mask, so use it to draw the hand opaquely. BmpContainer image, mask; bmp_init_container(hand->image_id, &image); bmp_init_container(hand->mask_id, &mask); 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(&image, &cx); flip_bitmap_x(&mask, NULL); } if (hand->flip_y) { // We can also do this vertically. flip_bitmap_y(&image, &cy); flip_bitmap_y(&mask, NULL); } GRect destination = layer_get_frame(&image.layer.layer); destination.origin.x = place_x - cx; destination.origin.y = place_y - cy; graphics_context_set_compositing_mode(ctx, GCompOpOr); graphics_draw_bitmap_in_rect(ctx, &mask.bmp, destination); graphics_context_set_compositing_mode(ctx, GCompOpClear); graphics_draw_bitmap_in_rect(ctx, &image.bmp, destination); bmp_deinit_container(&image); bmp_deinit_container(&mask); } }
// 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); } }