mirror of
https://github.com/google/pebble.git
synced 2025-07-16 02:56:43 -04:00
Import of the watch repository from Pebble
This commit is contained in:
commit
3b92768480
10334 changed files with 2564465 additions and 0 deletions
80
src/fw/applib/graphics/perimeter.c
Normal file
80
src/fw/applib/graphics/perimeter.c
Normal file
|
@ -0,0 +1,80 @@
|
|||
/*
|
||||
* 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/perimeter.h"
|
||||
|
||||
#include "system/passert.h"
|
||||
#include "util/math.h"
|
||||
|
||||
static uint16_t prv_triangle_side(uint16_t hypotenuse, uint16_t side) {
|
||||
// third side of triangle based on pythagorean theorem
|
||||
return integer_sqrt(ABS(((uint32_t)hypotenuse * hypotenuse) - ((uint32_t)side * side)));
|
||||
}
|
||||
|
||||
T_STATIC GRangeHorizontal perimeter_for_circle(GRangeVertical vertical_range, GPoint center,
|
||||
int32_t radius) {
|
||||
radius = MAX(0, radius);
|
||||
int32_t height = 0;
|
||||
int32_t width = 0;
|
||||
|
||||
const int32_t top = center.y - radius;
|
||||
const int32_t bottom = center.y + radius;
|
||||
|
||||
int32_t range_start = vertical_range.origin_y;
|
||||
int32_t range_end = vertical_range.origin_y + vertical_range.size_h;
|
||||
|
||||
// Check if both top and bottom are outside but not surrounding the perimeter
|
||||
if ((range_start < top && range_end < top) ||
|
||||
(range_start > bottom && range_end > bottom)) {
|
||||
return (GRangeHorizontal){0, 0};
|
||||
}
|
||||
|
||||
range_start = CLIP(range_start, top, bottom);
|
||||
range_end = CLIP(range_end, top, bottom);
|
||||
|
||||
// height of triangle from center to range start
|
||||
height = ABS(center.y - range_start);
|
||||
const int32_t start_width = prv_triangle_side(radius, height);
|
||||
|
||||
// height of triangle from center to range end
|
||||
height = ABS(center.y - range_end);
|
||||
const int32_t end_width = prv_triangle_side(radius, height);
|
||||
|
||||
width = MIN(start_width, end_width);
|
||||
|
||||
return (GRangeHorizontal){.origin_x = center.x - width, .size_w = width * 2};
|
||||
}
|
||||
|
||||
T_STATIC GRangeHorizontal perimeter_for_display_round(const GPerimeter *perimeter,
|
||||
const GSize *ctx_size,
|
||||
GRangeVertical vertical_range,
|
||||
uint16_t inset) {
|
||||
const GRect frame = (GRect) { GPointZero, *ctx_size };
|
||||
const GPoint center = grect_center_point(&frame);
|
||||
const int32_t radius = grect_shortest_side(frame) / 2 - inset;
|
||||
return perimeter_for_circle(vertical_range, center, radius);
|
||||
}
|
||||
|
||||
T_STATIC GRangeHorizontal perimeter_for_display_rect(const GPerimeter *perimeter,
|
||||
const GSize *ctx_size,
|
||||
GRangeVertical vertical_range,
|
||||
uint16_t inset) {
|
||||
return (GRangeHorizontal){.origin_x = inset, .size_w = MAX(0, ctx_size->w - 2 * inset)};
|
||||
}
|
||||
|
||||
const GPerimeter * const g_perimeter_for_display = &(const GPerimeter) {
|
||||
.callback = PBL_IF_RECT_ELSE(perimeter_for_display_rect, perimeter_for_display_round),
|
||||
};
|
Loading…
Add table
Add a link
Reference in a new issue