Import of the watch repository from Pebble

This commit is contained in:
Matthieu Jeanson 2024-12-12 16:43:03 -08:00 committed by Katharine Berry
commit 3b92768480
10334 changed files with 2564465 additions and 0 deletions

View file

@ -0,0 +1,161 @@
/*
* 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 "animation_timing.h"
#include "animation_interpolate.h"
#include "system/logging.h"
#include "system/passert.h"
#include "util/math_fixed.h"
#include "util/size.h"
//! @file animation_timing.c
static const uint16_t s_ease_in_table[] = {
0, 64, 256, 576,
1024, 1600, 2304, 3136,
4096, 5184, 6400, 7744,
9216, 10816, 12544, 14400,
16384, 18496, 20736, 23104,
25600, 28224, 30976, 33856,
36864, 40000, 43264, 46656,
50176, 53824, 57600, 61504,
65535
};
static const uint16_t s_ease_out_table[] = {
0, 4031, 7935, 11711,
15359, 18879, 22271, 25535,
28671, 31679, 34559, 37311,
39935, 42431, 44799, 47039,
49151, 51135, 52991, 54719,
56319, 57791, 59135, 60351,
61439, 62399, 63231, 63935,
64511, 64959, 65279, 65471,
65535
};
static const uint16_t s_ease_in_out_table[] = {
0, 128, 512, 1152,
2048, 3200, 4608, 6272,
8192, 10368, 12800, 15488,
18432, 21632, 25088, 28800,
32770, 36737, 40449, 43905,
47105, 50049, 52737, 55169,
57345, 59265, 60929, 62337,
63488, 64384, 65024, 65408,
65535
};
typedef struct {
const size_t num_entries;
const uint16_t *table;
} EasingTable;
static const EasingTable s_easing_tables[] = {
[AnimationCurveEaseIn] = { ARRAY_LENGTH(s_ease_in_table), s_ease_in_table },
[AnimationCurveEaseOut] = { ARRAY_LENGTH(s_ease_out_table), s_ease_out_table },
[AnimationCurveEaseInOut] = { ARRAY_LENGTH(s_ease_in_out_table), s_ease_in_out_table },
};
int32_t animation_timing_segmented(int32_t time_normalized, int32_t index,
uint32_t num_segments, Fixed_S32_16 duration_fraction) {
PBL_ASSERTN(num_segments > 0 && duration_fraction.raw_value > 0);
if (index < 0) {
return ANIMATION_NORMALIZED_MAX;
}
if ((uint32_t)index >= num_segments) {
return 0;
}
const int32_t duration_per_item = ((int64_t) ANIMATION_NORMALIZED_MAX
* duration_fraction.raw_value) / FIXED_S32_16_ONE.raw_value;
const int32_t delay_per_item = (ANIMATION_NORMALIZED_MAX - duration_per_item) / num_segments;
const int32_t normalized_offset = time_normalized - index * delay_per_item;
if (normalized_offset < 0) {
return 0;
}
const int32_t relative_progress = ((int64_t) normalized_offset
* FIXED_S32_16_ONE.raw_value) / duration_fraction.raw_value;
if (relative_progress > ANIMATION_NORMALIZED_MAX) {
return ANIMATION_NORMALIZED_MAX;
}
return relative_progress;
}
typedef int64_t (*ArrayAccessorInt64)(const void *array, size_t index);
static int64_t prv_uint16_getter(const void *array, size_t idx) {
return ((uint16_t*)array)[idx];
}
static int64_t prv_int32_getter(const void *array, size_t idx) {
return ((int32_t*)array)[idx];
}
AnimationProgress prv_animation_timing_interpolate(AnimationProgress progress, const void *array,
ArrayAccessorInt64 getter, size_t num_entries) {
PBL_ASSERTN(num_entries > 0);
const size_t max_entry = num_entries - 1;
if (progress <= ANIMATION_NORMALIZED_MIN) {
return (AnimationProgress) getter(array, 0);
}
if (progress >= ANIMATION_NORMALIZED_MAX) {
return (AnimationProgress) getter(array, max_entry);
}
// Linear interpolate from the easing table.
const size_t stride = ANIMATION_NORMALIZED_MAX / max_entry;
const size_t index = (progress * max_entry) / ANIMATION_NORMALIZED_MAX;
const int64_t from = getter(array, index);
const int64_t delta = getter(array, index + 1) - from;
return (AnimationProgress) (from + (delta * (progress - index * stride)) / stride);
}
AnimationProgress animation_timing_interpolate(
AnimationProgress time_normalized, const uint16_t *table, size_t num_entries) {
return prv_animation_timing_interpolate(time_normalized, table, prv_uint16_getter, num_entries);
}
AnimationProgress animation_timing_interpolate32(
AnimationProgress time_normalized, const int32_t *table, size_t num_entries) {
return prv_animation_timing_interpolate(time_normalized, table, prv_int32_getter, num_entries);
}
AnimationProgress animation_timing_curve(AnimationProgress time_normalized,
AnimationCurve curve) {
switch (curve) {
case AnimationCurveEaseIn:
case AnimationCurveEaseOut:
case AnimationCurveEaseInOut: {
const EasingTable *easing = &s_easing_tables[curve];
return animation_timing_interpolate(time_normalized, easing->table, easing->num_entries);
}
case AnimationCurveLinear:
default:
return time_normalized;
}
}
AnimationProgress animation_timing_scaled(AnimationProgress time_normalized,
AnimationProgress interval_start,
AnimationProgress interval_end) {
int64_t result = time_normalized - interval_start;
result = (result * ANIMATION_NORMALIZED_MAX) / (interval_end - interval_start);
// no overflow worries here, result and ANIMATION_NORMALIZED_MAX are both <= 2^16.
return (AnimationProgress)result;
}