mirror of
https://github.com/google/pebble.git
synced 2025-05-25 12:44:53 +00:00
Import of the watch repository from Pebble
This commit is contained in:
commit
3b92768480
10334 changed files with 2564465 additions and 0 deletions
345
tests/fw/graphics/test_gbitmap_sequence.c
Normal file
345
tests/fw/graphics/test_gbitmap_sequence.c
Normal file
|
@ -0,0 +1,345 @@
|
|||
/*
|
||||
* Copyright 2024 Google LLC
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include "applib/graphics/gbitmap_sequence.h"
|
||||
#include "applib/graphics/graphics.h"
|
||||
|
||||
#include "clar.h"
|
||||
#include "util.h"
|
||||
|
||||
#include <util/size.h>
|
||||
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#include <time.h>
|
||||
|
||||
// Test files are Creative Commons 0 (ie. Public Domain) from
|
||||
// http://opengameart.org/content/game-character-blue-flappy-bird-sprite-sheets
|
||||
// http://opengameart.org/content/pixel-puncher-sprites
|
||||
// http://opengameart.org/content/spike-man-monster
|
||||
// http://opengameart.org/content/platformer-baddies
|
||||
// http://opengameart.org/content/greyscale-special-effects-%E2%80%94-various-dimensions-and-flavours
|
||||
// http://opengameart.org/content/bouncing-ball-guy
|
||||
// http://opengameart.org/content/medals-3
|
||||
// http://opengameart.org/content/open-pixel-platformer-tiles-sprites
|
||||
|
||||
#if SCREEN_COLOR_DEPTH_BITS == 8
|
||||
#include "applib/graphics/8_bit/framebuffer.c"
|
||||
#elif SCREEN_COLOR_DEPTH_BITS == 1
|
||||
#include "applib/graphics/1_bit/framebuffer.c"
|
||||
#endif
|
||||
|
||||
// Fakes
|
||||
////////////////////////////////////
|
||||
#include "fake_resource_syscalls.h"
|
||||
#include "fake_app_timer.h"
|
||||
|
||||
// Stubs
|
||||
////////////////////////////////////
|
||||
#include "stubs_applib_resource.h"
|
||||
#include "stubs_app_state.h"
|
||||
#include "stubs_logging.h"
|
||||
#include "stubs_heap.h"
|
||||
#include "stubs_passert.h"
|
||||
#include "stubs_pbl_malloc.h"
|
||||
#include "stubs_pebble_tasks.h"
|
||||
#include "stubs_print.h"
|
||||
#include "stubs_queue.h"
|
||||
#include "stubs_resources.h"
|
||||
#include "stubs_serial.h"
|
||||
#include "stubs_ui_window.h"
|
||||
|
||||
#define GET_PBI_NAME(x) prv_get_image_name(__func__, x, "pbi")
|
||||
#define GET_APNG_NAME prv_get_image_name(__func__, 0, "apng")
|
||||
|
||||
// Used to work around __func__ not being a string literal (necessary for macro concatenation)
|
||||
static const char *prv_get_image_name(const char* func_name, int index, const char *extension) {
|
||||
char *filename = malloc(PATH_STRING_LENGTH);
|
||||
if (index) {
|
||||
snprintf(filename, PATH_STRING_LENGTH, "%s_%u.%s", func_name, index, extension);
|
||||
} else {
|
||||
snprintf(filename, PATH_STRING_LENGTH, "%s.%s", func_name, extension);
|
||||
}
|
||||
return filename;
|
||||
}
|
||||
|
||||
// Tests
|
||||
////////////////////////////////////
|
||||
|
||||
// Reference PNGs reside in "tests/test_images/"
|
||||
// and are created at build time, with the files copied to TEST_IMAGES_PATH
|
||||
// and a separate PBI generated by bitmapgen.py from the PNG copied to TEST_IMAGES_PATH
|
||||
|
||||
// Tests APNG file with 2-bit color, 6 frames and loop = infinite
|
||||
// Tests start, stop, reset and loop
|
||||
// Result:
|
||||
// - gbitmaps matches platform decoded APNG
|
||||
void test_gbitmap_sequence__color_2bit_bouncing_ball(void) {
|
||||
#if PLATFROM_SPALDING
|
||||
uint32_t resource_id = sys_resource_load_file_as_resource(TEST_IMAGES_PATH, GET_APNG_NAME);
|
||||
cl_assert(resource_id != UINT32_MAX);
|
||||
|
||||
GBitmapSequence *bitmap_sequence = gbitmap_sequence_create_with_resource(resource_id);
|
||||
cl_assert(bitmap_sequence);
|
||||
|
||||
GBitmap *bitmap = gbitmap_create_blank(gbitmap_sequence_get_bitmap_size(bitmap_sequence),
|
||||
GBitmapFormat8Bit);
|
||||
cl_assert(bitmap);
|
||||
|
||||
gbitmap_sequence_update_bitmap_next_frame(bitmap_sequence, bitmap, NULL);
|
||||
cl_check(gbitmap_pbi_eq(bitmap, GET_PBI_NAME(1)));
|
||||
|
||||
gbitmap_sequence_update_bitmap_next_frame(bitmap_sequence, bitmap, NULL);
|
||||
cl_check(gbitmap_pbi_eq(bitmap, GET_PBI_NAME(2)));
|
||||
|
||||
gbitmap_sequence_update_bitmap_next_frame(bitmap_sequence, bitmap, NULL);
|
||||
cl_check(gbitmap_pbi_eq(bitmap, GET_PBI_NAME(3)));
|
||||
|
||||
gbitmap_sequence_update_bitmap_next_frame(bitmap_sequence, bitmap, NULL);
|
||||
cl_check(gbitmap_pbi_eq(bitmap, GET_PBI_NAME(4)));
|
||||
|
||||
gbitmap_sequence_update_bitmap_next_frame(bitmap_sequence, bitmap, NULL);
|
||||
cl_check(gbitmap_pbi_eq(bitmap, GET_PBI_NAME(5)));
|
||||
|
||||
gbitmap_sequence_update_bitmap_next_frame(bitmap_sequence, bitmap, NULL);
|
||||
cl_check(gbitmap_pbi_eq(bitmap, GET_PBI_NAME(6)));
|
||||
|
||||
// Test loop around
|
||||
gbitmap_sequence_update_bitmap_next_frame(bitmap_sequence, bitmap, NULL);
|
||||
cl_check(gbitmap_pbi_eq(bitmap, GET_PBI_NAME(1)));
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
// Tests APNG file with 8-bit color, 88 frames of delay 100ms each and loop = 2
|
||||
// Tests gbitmap_sequence_update_bitmap_by_elapsed
|
||||
// Result:
|
||||
// - gbitmaps matches platform decoded APNG
|
||||
void test_gbitmap_sequence__color_8bit_fight(void) {
|
||||
#if PLATFORM_SPALDING
|
||||
bool status = false;
|
||||
uint32_t resource_id = sys_resource_load_file_as_resource(TEST_IMAGES_PATH, GET_APNG_NAME);
|
||||
cl_assert(resource_id != UINT32_MAX);
|
||||
|
||||
GBitmapSequence *bitmap_sequence = gbitmap_sequence_create_with_resource(resource_id);
|
||||
cl_assert(bitmap_sequence);
|
||||
|
||||
GBitmap *bitmap = gbitmap_create_blank(gbitmap_sequence_get_bitmap_size(bitmap_sequence),
|
||||
GBitmapFormat8Bit);
|
||||
cl_assert(bitmap);
|
||||
|
||||
// first frame always shows at the beginning (0 ms)
|
||||
status = gbitmap_sequence_update_bitmap_by_elapsed(bitmap_sequence, bitmap, 0);
|
||||
cl_assert_equal_b(status, true);
|
||||
cl_check(gbitmap_pbi_eq(bitmap, GET_PBI_NAME(1)));
|
||||
|
||||
// each frame has delay 100ms, so (33 - 1) * 100 ms shows 33rd frame
|
||||
status = gbitmap_sequence_update_bitmap_by_elapsed(bitmap_sequence, bitmap, (33 - 1) * 100);
|
||||
cl_assert_equal_b(status, true);
|
||||
cl_check(gbitmap_pbi_eq(bitmap, GET_PBI_NAME(33)));
|
||||
|
||||
status = gbitmap_sequence_update_bitmap_by_elapsed(bitmap_sequence, bitmap, (60 - 1) * 100);
|
||||
cl_assert_equal_b(status, true);
|
||||
cl_check(gbitmap_pbi_eq(bitmap, GET_PBI_NAME(60)));
|
||||
|
||||
// Since we have loop count 2 and 88 frames, see if we can go to elapsed at 2nd loop correctly
|
||||
status = gbitmap_sequence_update_bitmap_by_elapsed(bitmap_sequence, bitmap,
|
||||
88 * 100 + (49 - 1) * 100);
|
||||
cl_assert_equal_b(status, true);
|
||||
cl_check(gbitmap_pbi_eq(bitmap, GET_PBI_NAME(49)));
|
||||
|
||||
// Since loop only equals 2, make sure that huge elapsed time leaves us at final frame
|
||||
status = gbitmap_sequence_update_bitmap_by_elapsed(bitmap_sequence, bitmap, 12345 * 100);
|
||||
cl_assert_equal_b(status, true);
|
||||
cl_check(gbitmap_pbi_eq(bitmap, GET_PBI_NAME(88)));
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
// Tests APNG file with 8-bit color, 5 frames and loop = 1
|
||||
// Tests gbitmap_sequence_update_bitmap_by_elapsed with 0 delay frames for 1, 4 and 5
|
||||
// and 2 & 3 have delay 1000ms
|
||||
// Result:
|
||||
// - gbitmaps matches platform decoded APNG
|
||||
void test_gbitmap_sequence__color_8bit_coin(void) {
|
||||
#if PLATFORM_SPALDING
|
||||
uint32_t resource_id = sys_resource_load_file_as_resource(TEST_IMAGES_PATH, GET_APNG_NAME);
|
||||
cl_assert(resource_id != UINT32_MAX);
|
||||
|
||||
GBitmapSequence *bitmap_sequence = gbitmap_sequence_create_with_resource(resource_id);
|
||||
cl_assert(bitmap_sequence);
|
||||
|
||||
GBitmap *bitmap = gbitmap_create_blank(gbitmap_sequence_get_bitmap_size(bitmap_sequence),
|
||||
GBitmapFormat8Bit);
|
||||
cl_assert(bitmap);
|
||||
|
||||
// Since frame 1 has 0 delay, it renders then immediately we render frame 2
|
||||
gbitmap_sequence_update_bitmap_by_elapsed(bitmap_sequence, bitmap, 0);
|
||||
cl_check(gbitmap_pbi_eq(bitmap, GET_PBI_NAME(2)));
|
||||
|
||||
|
||||
// Frame 2 has delay 1000 ms, so at time 1000 ms, we expect frame 3
|
||||
gbitmap_sequence_update_bitmap_by_elapsed(bitmap_sequence, bitmap, 1 * 1000);
|
||||
cl_check(gbitmap_pbi_eq(bitmap, GET_PBI_NAME(3)));
|
||||
|
||||
// Frame 3 has delay 1000 ms, frame 4 and 5 have zero delay, so at time 2000 ms == frame 5
|
||||
gbitmap_sequence_update_bitmap_by_elapsed(bitmap_sequence, bitmap, 2 * 1000);
|
||||
cl_check(gbitmap_pbi_eq(bitmap, GET_PBI_NAME(5)));
|
||||
|
||||
// Since loop only equals 1, make sure that huge elapsed time leaves us at final frame
|
||||
gbitmap_sequence_update_bitmap_by_elapsed(bitmap_sequence, bitmap, 12345 * 1000);
|
||||
cl_check(gbitmap_pbi_eq(bitmap, GET_PBI_NAME(5)));
|
||||
#endif
|
||||
}
|
||||
|
||||
// Tests APNG file with 8-bit color, 5 frames and loop = 1
|
||||
// Tests gbitmap_sequence_update_bitmap_by_elapsed with 0 delay frames for 1, 4 and 5
|
||||
// and 2 & 3 have delay 1000ms
|
||||
// Result:
|
||||
// - gbitmaps matches platform decoded APNG
|
||||
void test_gbitmap_sequence__color_8bit_coin_round(void) {
|
||||
#if PLATFORM_SPALDING
|
||||
uint32_t resource_id = sys_resource_load_file_as_resource(
|
||||
TEST_IMAGES_PATH, "test_gbitmap_sequence__color_8bit_coin.apng");
|
||||
cl_assert(resource_id != UINT32_MAX);
|
||||
|
||||
GBitmapSequence *bitmap_sequence = gbitmap_sequence_create_with_resource(resource_id);
|
||||
cl_assert(bitmap_sequence);
|
||||
|
||||
GBitmap *bitmap = gbitmap_create_blank(GSize(180, 180), GBitmapFormat8BitCircular);
|
||||
cl_assert(bitmap);
|
||||
|
||||
// Since frame 1 has 0 delay, it renders then immediately we render frame 2
|
||||
gbitmap_sequence_update_bitmap_by_elapsed(bitmap_sequence, bitmap, 0);
|
||||
cl_check(gbitmap_pbi_eq(bitmap, GET_PBI_NAME(2)));
|
||||
|
||||
// Frame 2 has delay 1000 ms, so at time 1000 ms, we expect frame 3
|
||||
gbitmap_sequence_update_bitmap_by_elapsed(bitmap_sequence, bitmap, 1 * 1000);
|
||||
cl_check(gbitmap_pbi_eq(bitmap, GET_PBI_NAME(3)));
|
||||
|
||||
// Frame 3 has delay 1000 ms, frame 4 and 5 have zero delay, so at time 2000 ms == frame 5
|
||||
gbitmap_sequence_update_bitmap_by_elapsed(bitmap_sequence, bitmap, 2 * 1000);
|
||||
cl_check(gbitmap_pbi_eq(bitmap, GET_PBI_NAME(5)));
|
||||
|
||||
// Since loop only equals 1, make sure that huge elapsed time leaves us at final frame
|
||||
gbitmap_sequence_update_bitmap_by_elapsed(bitmap_sequence, bitmap, 12345 * 1000);
|
||||
cl_check(gbitmap_pbi_eq(bitmap, GET_PBI_NAME(5)));
|
||||
#endif
|
||||
}
|
||||
|
||||
// Tests APNG file with 8-bit color, 5 frames and loop infinite, size 64x64
|
||||
// Tests gbitmap_sequence for bitmap bounds offset and DISPOSE_OP_BACKGROUND
|
||||
// Result:
|
||||
// - gbitmaps matches platform decoded APNG
|
||||
void test_gbitmap_sequence__color_8bit_bounds(void) {
|
||||
#if PLATFORM_SPALDING
|
||||
uint32_t resource_id = sys_resource_load_file_as_resource(TEST_IMAGES_PATH, GET_APNG_NAME);
|
||||
cl_assert(resource_id != UINT32_MAX);
|
||||
|
||||
GRect orig_bounds = GRect(0, 0, 180, 180);
|
||||
int xshift = 71;
|
||||
int yshift = 39;
|
||||
GRect shift_bounds = GRect(xshift, yshift,
|
||||
orig_bounds.size.w - xshift,
|
||||
orig_bounds.size.h - yshift);
|
||||
|
||||
GBitmapSequence *bitmap_sequence = gbitmap_sequence_create_with_resource(resource_id);
|
||||
cl_assert(bitmap_sequence);
|
||||
|
||||
GBitmap *bitmap = gbitmap_create_blank(orig_bounds.size, GBitmapFormat8BitCircular);
|
||||
cl_assert(bitmap);
|
||||
|
||||
// Shift the bounds when updating
|
||||
gbitmap_set_bounds(bitmap, shift_bounds);
|
||||
gbitmap_sequence_update_bitmap_next_frame(bitmap_sequence, bitmap, NULL);
|
||||
// set the original bounds to do whole-image comparison
|
||||
gbitmap_set_bounds(bitmap, orig_bounds);
|
||||
cl_check(gbitmap_pbi_eq(bitmap, GET_PBI_NAME(1)));
|
||||
|
||||
gbitmap_set_bounds(bitmap, shift_bounds);
|
||||
gbitmap_sequence_update_bitmap_next_frame(bitmap_sequence, bitmap, NULL);
|
||||
gbitmap_set_bounds(bitmap, orig_bounds);
|
||||
cl_check(gbitmap_pbi_eq(bitmap, GET_PBI_NAME(2)));
|
||||
|
||||
gbitmap_set_bounds(bitmap, shift_bounds);
|
||||
gbitmap_sequence_update_bitmap_next_frame(bitmap_sequence, bitmap, NULL);
|
||||
gbitmap_set_bounds(bitmap, orig_bounds);
|
||||
cl_check(gbitmap_pbi_eq(bitmap, GET_PBI_NAME(3)));
|
||||
|
||||
gbitmap_set_bounds(bitmap, shift_bounds);
|
||||
gbitmap_sequence_update_bitmap_next_frame(bitmap_sequence, bitmap, NULL);
|
||||
gbitmap_set_bounds(bitmap, orig_bounds);
|
||||
cl_check(gbitmap_pbi_eq(bitmap, GET_PBI_NAME(4)));
|
||||
|
||||
gbitmap_set_bounds(bitmap, shift_bounds);
|
||||
gbitmap_sequence_update_bitmap_next_frame(bitmap_sequence, bitmap, NULL);
|
||||
gbitmap_set_bounds(bitmap, orig_bounds);
|
||||
cl_check(gbitmap_pbi_eq(bitmap, GET_PBI_NAME(5)));
|
||||
#endif
|
||||
}
|
||||
|
||||
// Tests APNG file with 8-bit color, originally broke the updated upng+tinflate code
|
||||
// Result:
|
||||
// - gbitmaps matches platform decoded APNG
|
||||
void test_gbitmap_sequence__color_8bit_yoshi(void) {
|
||||
#if PLATFORM_SPALDING
|
||||
bool status = false;
|
||||
uint32_t resource_id = sys_resource_load_file_as_resource(TEST_IMAGES_PATH, GET_APNG_NAME);
|
||||
cl_assert(resource_id != UINT32_MAX);
|
||||
GBitmapSequence *bitmap_sequence = gbitmap_sequence_create_with_resource(resource_id);
|
||||
GBitmap *bitmap = gbitmap_create_blank(gbitmap_sequence_get_bitmap_size(bitmap_sequence),
|
||||
GBitmapFormat8Bit);
|
||||
|
||||
status = gbitmap_sequence_update_bitmap_next_frame(bitmap_sequence, bitmap, NULL);
|
||||
cl_assert_equal_b(status, true);
|
||||
cl_check(gbitmap_pbi_eq(bitmap, GET_PBI_NAME(1)));
|
||||
|
||||
status = gbitmap_sequence_update_bitmap_next_frame(bitmap_sequence, bitmap, NULL);
|
||||
cl_assert_equal_b(status, true);
|
||||
cl_check(gbitmap_pbi_eq(bitmap, GET_PBI_NAME(2)));
|
||||
|
||||
status = gbitmap_sequence_update_bitmap_next_frame(bitmap_sequence, bitmap, NULL);
|
||||
cl_assert_equal_b(status, true);
|
||||
cl_check(gbitmap_pbi_eq(bitmap, GET_PBI_NAME(3)));
|
||||
#endif
|
||||
}
|
||||
|
||||
void test_gbitmap_sequence__1bit_to_1bit_notification(void) {
|
||||
uint32_t resource_id = sys_resource_load_file_as_resource(TEST_IMAGES_PATH, GET_APNG_NAME);
|
||||
cl_assert(resource_id != UINT32_MAX);
|
||||
GBitmapSequence *bitmap_sequence = gbitmap_sequence_create_with_resource(resource_id);
|
||||
GBitmap *bitmap = gbitmap_create_blank(gbitmap_sequence_get_bitmap_size(bitmap_sequence),
|
||||
GBitmapFormat1Bit);
|
||||
|
||||
// We're interested in checking the following frames
|
||||
const int check_frames[] = { 1, 4, 23, 24, 25, 31, 75 };
|
||||
|
||||
int current_frame = 0;
|
||||
for (int i = 0; i < ARRAY_LENGTH(check_frames); ++i) {
|
||||
// Advance to the next frame we're interested in.
|
||||
for (; current_frame < check_frames[i]; ++current_frame) {
|
||||
bool status = gbitmap_sequence_update_bitmap_next_frame(bitmap_sequence, bitmap, NULL);
|
||||
cl_assert_equal_b(status, true);
|
||||
}
|
||||
|
||||
printf("Checking %u\n", current_frame);
|
||||
|
||||
// Don't use GET_PBI_NAME, it doesn't like not using anything other than an integer literal
|
||||
char filename_buffer[128];
|
||||
snprintf(filename_buffer, sizeof(filename_buffer), "%s_%u.pbi", __func__, current_frame);
|
||||
cl_check(gbitmap_pbi_eq(bitmap, filename_buffer));
|
||||
}
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue