mirror of
https://github.com/google/pebble.git
synced 2025-03-24 20:49:05 +00:00
306 lines
11 KiB
C
306 lines
11 KiB
C
/*
|
|
* 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/graphics.h"
|
|
#include "applib/graphics/framebuffer.h"
|
|
#include "applib/graphics/gtransform.h"
|
|
#include "util/trig.h"
|
|
|
|
#include "util/math_fixed.h"
|
|
|
|
#include "clar.h"
|
|
|
|
#include <stdio.h>
|
|
#include <string.h>
|
|
|
|
// Helper Functions
|
|
////////////////////////////////////
|
|
|
|
// Stubs
|
|
////////////////////////////////////
|
|
#include "stubs_app_state.h"
|
|
#include "stubs_applib_resource.h"
|
|
#include "stubs_compiled_with_legacy2_sdk.h"
|
|
#include "stubs_heap.h"
|
|
#include "stubs_logging.h"
|
|
#include "stubs_passert.h"
|
|
#include "stubs_pbl_malloc.h"
|
|
#include "stubs_pebble_tasks.h"
|
|
#include "stubs_print.h"
|
|
#include "stubs_resources.h"
|
|
#include "stubs_serial.h"
|
|
#include "stubs_syscalls.h"
|
|
#include "stubs_ui_window.h"
|
|
#include "stubs_unobstructed_area.h"
|
|
|
|
|
|
// Tests
|
|
////////////////////////////////////
|
|
|
|
/////////////////////////////////
|
|
/// Generic matrix tests
|
|
/////////////////////////////////
|
|
void test_graphics_gtransform_${BIT_DEPTH_NAME}__types_gtransformnumber(void) {
|
|
GTransform t_c; // matrix to compare against
|
|
GTransformNumber tn;
|
|
int32_t test_num;
|
|
|
|
tn = GTransformNumberFromNumber(1);
|
|
test_num = (int32_t)((float)1 * (1 << FIXED_S32_16_PRECISION));
|
|
cl_assert((memcmp(&tn, &test_num, sizeof(GTransformNumber)) == 0));
|
|
|
|
tn = GTransformNumberFromNumber(3.5);
|
|
test_num = (int32_t)((float)3.5 * (1 << FIXED_S32_16_PRECISION));
|
|
cl_assert((memcmp(&tn, &test_num, sizeof(GTransformNumber)) == 0));
|
|
|
|
tn = GTransformNumberFromNumber(-2);
|
|
test_num = (int32_t)((float)-2 * (1 << FIXED_S32_16_PRECISION));
|
|
cl_assert((memcmp(&tn, &test_num, sizeof(GTransformNumber)) == 0));
|
|
|
|
tn = GTransformNumberFromNumber(-3.5);
|
|
test_num = (int32_t)((float)-3.5 * (1 << FIXED_S32_16_PRECISION));
|
|
cl_assert((memcmp(&tn, &test_num, sizeof(GTransformNumber)) == 0));
|
|
|
|
t_c = GTransform(GTransformNumberFromNumber(1), GTransformNumberFromNumber(2),
|
|
GTransformNumberFromNumber(3), GTransformNumberFromNumber(4),
|
|
GTransformNumberFromNumber(5), GTransformNumberFromNumber(6));
|
|
|
|
int32_t test_array[6] = {1 * (1 << FIXED_S32_16_PRECISION),
|
|
2 * (1 << FIXED_S32_16_PRECISION),
|
|
3 * (1 << FIXED_S32_16_PRECISION),
|
|
4 * (1 << FIXED_S32_16_PRECISION),
|
|
5 * (1 << FIXED_S32_16_PRECISION),
|
|
6 * (1 << FIXED_S32_16_PRECISION)};
|
|
|
|
cl_assert((memcmp(&t_c, &test_array, sizeof(GTransform)) == 0));
|
|
cl_assert(gtransform_is_equal(&t_c, (const GTransform*)&test_array));
|
|
|
|
t_c = GTransformFromNumbers(1, 2, 3, 4, 5, 6);
|
|
cl_assert(gtransform_is_equal(&t_c, (const GTransform*)&test_array));
|
|
|
|
// Test to make sure implemented rotation calculation is correct
|
|
int32_t angle = DEG_TO_TRIGANGLE(45);
|
|
int32_t cosine = cos_lookup(angle);
|
|
GTransformNumber num = GTransformNumberFromNumber((float)cosine / TRIG_MAX_RATIO);
|
|
GTransformNumber num2 =
|
|
(GTransformNumber) { .raw_value = (int32_t)(((int64_t)cosine *
|
|
GTransformNumberOne.raw_value) / TRIG_MAX_RATIO) };
|
|
cl_assert(num.raw_value == num2.raw_value);
|
|
|
|
}
|
|
|
|
void test_graphics_gtransform_${BIT_DEPTH_NAME}__types_precise(void) {
|
|
GPointPrecise pointP = GPointPreciseFromGPoint(GPoint(2, 5));
|
|
GPointPrecise pointP_c = GPointPrecise((2 % GPOINT_PRECISE_MAX) << GPOINT_PRECISE_PRECISION,
|
|
(5 % GPOINT_PRECISE_MAX) << GPOINT_PRECISE_PRECISION);
|
|
|
|
cl_assert(gpointprecise_equal(&pointP, &pointP_c));
|
|
|
|
GVectorPrecise vectorP = GVectorPreciseFromGVector(GVector(2, 5));
|
|
GVectorPrecise vectorP_c = GVectorPrecise((2 % GVECTOR_PRECISE_MAX) << GVECTOR_PRECISE_PRECISION,
|
|
(5 % GVECTOR_PRECISE_MAX) << GVECTOR_PRECISE_PRECISION);
|
|
|
|
cl_assert(gvectorprecise_equal(&vectorP, &vectorP_c));
|
|
}
|
|
|
|
void test_graphics_gtransform_${BIT_DEPTH_NAME}__init(void) {
|
|
GTransform t;
|
|
GTransform t_c; // matrix to compare against
|
|
|
|
// Test Identity Matrix
|
|
t = GTransformIdentity();
|
|
t_c = GTransformFromNumbers(1, 0, 0, 1, 0, 0);
|
|
|
|
cl_assert(gtransform_is_equal(&t, &t_c));
|
|
cl_assert(gtransform_is_identity(&t));
|
|
cl_assert(gtransform_is_identity(&t_c));
|
|
|
|
// Test Scale Matrix
|
|
t = GTransformScale(GTransformNumberFromNumber(2), GTransformNumberFromNumber(5));
|
|
t_c = GTransformFromNumbers(2, 0, 0, 5, 0, 0);
|
|
|
|
cl_assert(gtransform_is_equal(&t, &t_c));
|
|
cl_assert(gtransform_is_only_scale(&t));
|
|
cl_assert(gtransform_is_only_scale(&t_c));
|
|
|
|
t_c = GTransformScaleFromNumber(2, 5);
|
|
cl_assert(gtransform_is_equal(&t, &t_c));
|
|
|
|
// Test Translation Matrix
|
|
t = GTransformTranslation(GTransformNumberFromNumber(2), GTransformNumberFromNumber(5));
|
|
t_c = GTransformFromNumbers(1, 0, 0, 1, 2, 5);
|
|
|
|
cl_assert(gtransform_is_equal(&t, &t_c));
|
|
cl_assert(gtransform_is_only_translation(&t));
|
|
cl_assert(gtransform_is_only_translation(&t_c));
|
|
|
|
t_c = GTransformTranslationFromNumber(2, 5);
|
|
cl_assert(gtransform_is_equal(&t, &t_c));
|
|
|
|
// Test Rotation Matrix
|
|
int32_t angle = DEG_TO_TRIGANGLE(45);
|
|
t = GTransformRotation(angle);
|
|
|
|
int32_t cosine = cos_lookup(angle);
|
|
int32_t sine = sin_lookup(angle);
|
|
|
|
t_c = GTransform(GTransformNumberFromNumber((float)cosine / TRIG_MAX_RATIO),
|
|
GTransformNumberFromNumber(-(float)sine / TRIG_MAX_RATIO),
|
|
GTransformNumberFromNumber((float)sine / TRIG_MAX_RATIO),
|
|
GTransformNumberFromNumber((float)cosine / TRIG_MAX_RATIO),
|
|
GTransformNumberZero,
|
|
GTransformNumberZero);
|
|
cl_assert(gtransform_is_equal(&t, &t_c));
|
|
|
|
angle = DEG_TO_TRIGANGLE(46);
|
|
cosine = cos_lookup(angle);
|
|
sine = sin_lookup(angle);
|
|
|
|
t_c = GTransform(GTransformNumberFromNumber((float)cosine / TRIG_MAX_RATIO),
|
|
GTransformNumberFromNumber(-(float)sine / TRIG_MAX_RATIO),
|
|
GTransformNumberFromNumber((float)sine / TRIG_MAX_RATIO),
|
|
GTransformNumberFromNumber((float)cosine / TRIG_MAX_RATIO),
|
|
GTransformNumberZero,
|
|
GTransformNumberZero);
|
|
cl_assert(!gtransform_is_equal(&t, &t_c));
|
|
|
|
t = GTransformRotation(0); // Should return identity if angle == 0
|
|
cl_assert(gtransform_is_identity(&t));
|
|
}
|
|
|
|
void test_graphics_gtransform_${BIT_DEPTH_NAME}__concat(void) {
|
|
GTransform t_new;
|
|
GTransform t1;
|
|
GTransform t2;
|
|
GTransform t_c; // matrix to compare against
|
|
|
|
// Test identity concatenation
|
|
t1 = GTransformIdentity();
|
|
t2 = GTransformIdentity();
|
|
t_c = GTransformIdentity();
|
|
|
|
gtransform_concat(&t_new, &t1, &t2);
|
|
cl_assert(gtransform_is_equal(&t_new, &t_c));
|
|
|
|
// Test identity concatenation with non-identity
|
|
t1 = GTransformFromNumbers(1, 2, 3, 4, 5, 6);
|
|
t2 = GTransformIdentity();
|
|
t_c = GTransformFromNumbers(1, 2, 3, 4, 5, 6);
|
|
gtransform_concat(&t_new, &t1, &t2);
|
|
cl_assert(gtransform_is_equal(&t_new, &t_c));
|
|
|
|
// Test pointer re-use
|
|
gtransform_concat(&t2, &t1, &t2);
|
|
cl_assert(gtransform_is_equal(&t2, &t_c));
|
|
|
|
// Test non-identity concatenation with identity
|
|
t1 = GTransformIdentity();
|
|
t2 = GTransformFromNumbers(1, 2, 3, 4, 5, 6);
|
|
t_c = GTransformFromNumbers(1, 2, 3, 4, 5, 6);
|
|
gtransform_concat(&t_new, &t1, &t2);
|
|
cl_assert(gtransform_is_equal(&t_new, &t_c));
|
|
|
|
// Test pointer re-use
|
|
gtransform_concat(&t1, &t1, &t2);
|
|
cl_assert(gtransform_is_equal(&t1, &t_c));
|
|
|
|
|
|
// Test concatenation of two non-identity matrices
|
|
t1 = GTransformFromNumbers(3, 5, 7, 11, 13, 17);
|
|
t2 = GTransformFromNumbers(1, 2, 3, 4, 5, 6);
|
|
t_c = GTransformFromNumbers(18, 26, 40, 58, 69, 100);
|
|
gtransform_concat(&t_new, &t1, &t2);
|
|
cl_assert(gtransform_is_equal(&t_new, &t_c));
|
|
}
|
|
|
|
void test_graphics_gtransform_${BIT_DEPTH_NAME}__scale(void) {
|
|
GTransform t_new;
|
|
GTransform t1;
|
|
GTransform t2;
|
|
GTransform t_c; // matrix to compare against
|
|
|
|
// Test scaling
|
|
t1 = GTransformFromNumbers(1, 2, 3, 4, 5, 6);
|
|
t2 = GTransformFromNumbers(1, 2, 3, 4, 5, 6);
|
|
t_c = GTransformFromNumbers(10, 20, 600, 800, 5, 6);
|
|
|
|
gtransform_scale(&t_new, &t1, GTransformNumberFromNumber(10), GTransformNumberFromNumber(200));
|
|
cl_assert(gtransform_is_equal(&t_new, &t_c));
|
|
cl_assert(gtransform_is_equal(&t1, &t2)); // ensure t1 has not changed
|
|
|
|
gtransform_scale_number(&t_new, &t1, 10, 200);
|
|
cl_assert(gtransform_is_equal(&t_new, &t_c));
|
|
cl_assert(gtransform_is_equal(&t1, &t2)); // ensure t1 has not changed
|
|
|
|
// Test pointer re-use
|
|
gtransform_scale(&t1, &t1, GTransformNumberFromNumber(10), GTransformNumberFromNumber(200));
|
|
cl_assert(gtransform_is_equal(&t1, &t_c));
|
|
}
|
|
|
|
void test_graphics_gtransform_${BIT_DEPTH_NAME}__translation(void) {
|
|
GTransform t_new;
|
|
GTransform t1;
|
|
GTransform t2;
|
|
GTransform t_c; // matrix to compare against
|
|
|
|
// Test translation
|
|
t1 = GTransformFromNumbers(1, 2, 3, 4, 5, 6);
|
|
t2 = GTransformFromNumbers(1, 2, 3, 4, 5, 6);
|
|
t_c = GTransformFromNumbers(1, 2, 3, 4, 615, 826);
|
|
|
|
gtransform_translate(&t_new, &t1,
|
|
GTransformNumberFromNumber(10), GTransformNumberFromNumber(200));
|
|
cl_assert(gtransform_is_equal(&t_new, &t_c));
|
|
cl_assert(gtransform_is_equal(&t1, &t2)); // ensure t1 has not changed
|
|
|
|
gtransform_translate_number(&t_new, &t1, 10, 200);
|
|
cl_assert(gtransform_is_equal(&t_new, &t_c));
|
|
cl_assert(gtransform_is_equal(&t1, &t2)); // ensure t1 has not changed
|
|
|
|
// Test pointer re-use
|
|
gtransform_translate(&t1, &t1, GTransformNumberFromNumber(10), GTransformNumberFromNumber(200));
|
|
cl_assert(gtransform_is_equal(&t1, &t_c));
|
|
}
|
|
|
|
|
|
void test_graphics_gtransform_${BIT_DEPTH_NAME}__rotation(void) {
|
|
GTransform t_new;
|
|
GTransform t1;
|
|
GTransform t2;
|
|
GTransform t_c; // matrix to compare against
|
|
|
|
// Test rotation
|
|
t1 = GTransformFromNumbers(10, 10, 10, 10, 10, 10);
|
|
t2 = GTransformFromNumbers(10, 10, 10, 10, 10, 10);
|
|
// Initialize a, b, c, and d based on the expected result
|
|
// a = b = 10*cos(45) - 10*sin(45)
|
|
// c = d = 10*sin(45) + 10*cos(45)
|
|
t_c = GTransform(GTransformNumberFromNumber(0),
|
|
GTransformNumberFromNumber(0),
|
|
(Fixed_S32_16){ .raw_value = (int32_t)(923960) },
|
|
(Fixed_S32_16){ .raw_value = (int32_t)(923960) },
|
|
GTransformNumberFromNumber(10),
|
|
GTransformNumberFromNumber(10));
|
|
|
|
gtransform_rotate(&t_new, &t1, DEG_TO_TRIGANGLE(45));
|
|
cl_assert(gtransform_is_equal(&t_new, &t_c));
|
|
cl_assert(gtransform_is_equal(&t1, &t2)); // ensure t1 has not changed
|
|
|
|
// Test pointer re-use
|
|
gtransform_rotate(&t1, &t1, DEG_TO_TRIGANGLE(45));
|
|
cl_assert(gtransform_is_equal(&t1, &t_c));
|
|
}
|
|
|