mirror of
https://github.com/google/pebble.git
synced 2025-05-25 20:53:11 +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
161
src/fw/applib/ui/animation_timing.c
Normal file
161
src/fw/applib/ui/animation_timing.c
Normal 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;
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue