mirror of
https://github.com/google/pebble.git
synced 2025-03-22 11:42:19 +00:00
258 lines
9.4 KiB
C
258 lines
9.4 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 "apps/system_apps/timeline/text_node.h"
|
|
|
|
#include "clar.h"
|
|
#include "pebble_asserts.h"
|
|
|
|
// Stubs
|
|
/////////////////////
|
|
|
|
#include "stubs_app_state.h"
|
|
#include "stubs_heap.h"
|
|
#include "stubs_passert.h"
|
|
#include "stubs_pbl_malloc.h"
|
|
#include "stubs_process_manager.h"
|
|
|
|
// TODO: PBL-22271 Complete timeline text node unit tests
|
|
|
|
// Fakes
|
|
/////////////////////
|
|
|
|
typedef struct GTextNodeTestData {
|
|
GContext gcontext;
|
|
GRect clip_box;
|
|
GTextNode *text_node;
|
|
GSize max_used_size;
|
|
} GTextNodeTestData;
|
|
|
|
GTextNodeTestData s_data;
|
|
|
|
#define TEST_TEXT "DUMMY TEXT"
|
|
#define TEST_FONT ((void *)0xf0a7f0a7)
|
|
#define TEST_TEXT_SIZE GSize(50, 18)
|
|
#define TEST_TEXT_BOX GRect(10, 10, 140, 200)
|
|
|
|
void graphics_draw_text(GContext *ctx, const char *text, GFont const font, const GRect box,
|
|
const GTextOverflowMode overflow_mode, const GTextAlignment alignment,
|
|
const GTextLayoutCacheRef layout_ref) {
|
|
GTextNodeText *text_node = (GTextNodeText *)s_data.text_node;
|
|
cl_assert(text_node);
|
|
cl_assert_equal_s(text_node->text, text);
|
|
cl_assert_equal_p(text_node->font, font);
|
|
cl_assert_equal_p(text_node->overflow, overflow_mode);
|
|
cl_assert_equal_p(text_node->alignment, alignment);
|
|
|
|
TextLayoutExtended *layout = (TextLayoutExtended *)layout_ref;
|
|
cl_assert_equal_p(text_node->line_spacing_delta, layout->line_spacing_delta);
|
|
|
|
layout->max_used_size = s_data.max_used_size;
|
|
}
|
|
|
|
GSize graphics_text_layout_get_max_used_size(GContext *ctx, const char *text,
|
|
GFont const font, const GRect box,
|
|
const GTextOverflowMode overflow_mode,
|
|
const GTextAlignment alignment,
|
|
GTextLayoutCacheRef layout_ref) {
|
|
GTextNodeText *text_node = (GTextNodeText *)s_data.text_node;
|
|
cl_assert(text_node);
|
|
cl_assert_equal_s(text_node->text, text);
|
|
cl_assert_equal_p(text_node->font, font);
|
|
cl_assert_equal_p(text_node->overflow, overflow_mode);
|
|
cl_assert_equal_p(text_node->alignment, alignment);
|
|
|
|
TextLayoutExtended *layout = (TextLayoutExtended *)layout_ref;
|
|
cl_assert_equal_p(text_node->line_spacing_delta, layout->line_spacing_delta);
|
|
|
|
layout->max_used_size = s_data.max_used_size;
|
|
return layout->max_used_size;
|
|
}
|
|
|
|
// Setup and Teardown
|
|
////////////////////////////////////
|
|
|
|
void test_graphics_text_node__initialize(void) {
|
|
s_data = (GTextNodeTestData) {};
|
|
}
|
|
|
|
void test_graphics_text_node__cleanup(void) {
|
|
}
|
|
|
|
// Tests
|
|
////////////////////////////////////
|
|
|
|
void test_graphics_text_node__text_draw(void) {
|
|
GContext *ctx = &s_data.gcontext;
|
|
GTextNodeText text_node = {};
|
|
text_node.text = (char *)TEST_TEXT;
|
|
text_node.font = TEST_FONT;
|
|
text_node.overflow = GTextOverflowModeTrailingEllipsis;
|
|
text_node.alignment = GTextAlignmentCenter;
|
|
|
|
s_data.text_node = &text_node.node;
|
|
s_data.max_used_size = TEST_TEXT_SIZE;
|
|
|
|
GSize size;
|
|
graphics_text_node_draw(&text_node.node, ctx, &TEST_TEXT_BOX, NULL, &size);
|
|
cl_assert(size.w > 0);
|
|
cl_assert(size.h > 0);
|
|
cl_assert_equal_i(size.w, TEST_TEXT_SIZE.w);
|
|
cl_assert_equal_i(size.h, TEST_TEXT_SIZE.h);
|
|
}
|
|
|
|
void test_graphics_text_node__text_size(void) {
|
|
GContext *ctx = &s_data.gcontext;
|
|
GTextNodeText text_node = {};
|
|
text_node.text = (char *)TEST_TEXT;
|
|
text_node.font = TEST_FONT;
|
|
text_node.overflow = GTextOverflowModeTrailingEllipsis;
|
|
text_node.alignment = GTextAlignmentCenter;
|
|
|
|
s_data.text_node = &text_node.node;
|
|
s_data.max_used_size = TEST_TEXT_SIZE;
|
|
|
|
GSize size;
|
|
graphics_text_node_get_size(&text_node.node, ctx, &TEST_TEXT_BOX, NULL, &size);
|
|
cl_assert(size.w > 0);
|
|
cl_assert(size.h > 0);
|
|
cl_assert_equal_i(size.w, TEST_TEXT_SIZE.w);
|
|
cl_assert_equal_i(size.h, TEST_TEXT_SIZE.h);
|
|
}
|
|
|
|
static int s_num_draw_custom_calls = 0;
|
|
|
|
static void prv_draw_custom(GContext *ctx, const GRect *box, const GTextNodeDrawConfig *config,
|
|
bool render, GSize *size_out, void *user_data) {
|
|
s_num_draw_custom_calls++;
|
|
*size_out = TEST_TEXT_SIZE;
|
|
}
|
|
|
|
void test_graphics_text_node__custom_cached_size(void) {
|
|
GContext *ctx = &s_data.gcontext;
|
|
GTextNodeCustom custom_node = {};
|
|
custom_node.node.type = GTextNodeType_Custom;
|
|
custom_node.callback = prv_draw_custom;
|
|
|
|
GSize size;
|
|
graphics_text_node_get_size(&custom_node.node, ctx, &TEST_TEXT_BOX, NULL, &size);
|
|
cl_assert(size.w > 0);
|
|
cl_assert(size.h > 0);
|
|
cl_assert_equal_i(size.w, TEST_TEXT_SIZE.w);
|
|
cl_assert_equal_i(size.h, TEST_TEXT_SIZE.h);
|
|
cl_assert_equal_i(size.w, custom_node.node.cached_size.w);
|
|
cl_assert_equal_i(size.h, custom_node.node.cached_size.h);
|
|
cl_assert_equal_i(s_num_draw_custom_calls, 1);
|
|
|
|
graphics_text_node_get_size(&custom_node.node, ctx, &TEST_TEXT_BOX, NULL, &size);
|
|
cl_assert(size.w > 0);
|
|
cl_assert(size.h > 0);
|
|
cl_assert_equal_i(size.w, TEST_TEXT_SIZE.w);
|
|
cl_assert_equal_i(size.h, TEST_TEXT_SIZE.h);
|
|
cl_assert_equal_i(size.w, custom_node.node.cached_size.w);
|
|
cl_assert_equal_i(size.h, custom_node.node.cached_size.h);
|
|
cl_assert_equal_i(s_num_draw_custom_calls, 1);
|
|
}
|
|
|
|
void test_graphics_text_node__create_container_nodes_buffer(void) {
|
|
GTextNodeHorizontal *h_empty = graphics_text_node_create_horizontal(0);
|
|
cl_assert_equal_i(h_empty->container.max_nodes, 0);
|
|
cl_assert_equal_p(NULL, h_empty->container.nodes);
|
|
|
|
GTextNodeHorizontal *h_nodes = graphics_text_node_create_horizontal(3);
|
|
cl_assert_equal_i(h_nodes->container.max_nodes, 3);
|
|
cl_assert_equal_p(h_nodes + 1, (void *)h_nodes->container.nodes);
|
|
|
|
GTextNodeVertical *v_empty = graphics_text_node_create_vertical(0);
|
|
cl_assert_equal_i(v_empty->container.max_nodes, 0);
|
|
cl_assert_equal_p(NULL, v_empty->container.nodes);
|
|
|
|
GTextNodeVertical *v_nodes = graphics_text_node_create_vertical(3);
|
|
cl_assert_equal_i(v_nodes->container.max_nodes, 3);
|
|
cl_assert_equal_p(v_nodes + 1, (void *)v_nodes->container.nodes);
|
|
}
|
|
|
|
void test_graphics_text_node__destroy(void) {
|
|
const char *str_a = "A";
|
|
GTextNodeText *text_a = graphics_text_node_create_text(strlen(str_a) + 1);
|
|
cl_assert(text_a->node.free_on_destroy);
|
|
strcpy((char *)text_a->text, str_a);
|
|
|
|
const char *str_b = task_strdup("B");
|
|
GTextNodeText *text_b = graphics_text_node_create_text(0);
|
|
cl_assert(text_b->node.free_on_destroy);
|
|
text_b->text = (char *)str_b;
|
|
|
|
const char *str_c = "C";
|
|
GTextNodeText text_c = {
|
|
.text = (char *)str_c,
|
|
};
|
|
cl_assert(!text_c.node.free_on_destroy);
|
|
|
|
GTextNodeCustom *custom_a = graphics_text_node_create_custom(NULL, NULL);
|
|
cl_assert(custom_a->node.free_on_destroy);
|
|
|
|
GTextNodeHorizontal *horizontal_a = graphics_text_node_create_horizontal(3);
|
|
cl_assert(horizontal_a->container.node.free_on_destroy);
|
|
cl_assert_equal_i(horizontal_a->container.max_nodes, 3);
|
|
cl_assert_equal_i(horizontal_a->container.num_nodes, 0);
|
|
cl_assert(graphics_text_node_container_add_child(&horizontal_a->container, &text_a->node));
|
|
cl_assert(graphics_text_node_container_add_child(&horizontal_a->container, &text_b->node));
|
|
cl_assert(graphics_text_node_container_add_child(&horizontal_a->container, &text_c.node));
|
|
cl_assert(!graphics_text_node_container_add_child(&horizontal_a->container, &custom_a->node));
|
|
cl_assert_equal_i(horizontal_a->container.num_nodes, 3);
|
|
|
|
GTextNodeVertical *vertical_a = graphics_text_node_create_vertical(2);
|
|
cl_assert(vertical_a->container.node.free_on_destroy);
|
|
cl_assert_equal_i(vertical_a->container.max_nodes, 2);
|
|
cl_assert_equal_i(vertical_a->container.num_nodes, 0);
|
|
cl_assert(graphics_text_node_container_add_child(&vertical_a->container, &horizontal_a->container.node));
|
|
cl_assert(graphics_text_node_container_add_child(&vertical_a->container, &custom_a->node));
|
|
cl_assert(!graphics_text_node_container_add_child(&vertical_a->container, &text_c.node));
|
|
cl_assert_equal_i(vertical_a->container.num_nodes, 2);
|
|
|
|
graphics_text_node_destroy(&vertical_a->container.node);
|
|
|
|
task_free((char *)str_b);
|
|
}
|
|
|
|
static void prv_draw_custom_clip(GContext *ctx, const GRect *box,
|
|
const GTextNodeDrawConfig *config, bool render, GSize *size_out,
|
|
void *user_data) {
|
|
cl_assert_equal_grect(ctx->draw_state.clip_box, s_data.clip_box);
|
|
}
|
|
|
|
#define TEST_CLIP_BOX GRect(10, 20, 30, 40)
|
|
|
|
void test_graphics_text_node__clip(void) {
|
|
GContext *ctx = &s_data.gcontext;
|
|
GTextNodeCustom custom_node = {};
|
|
custom_node.node.type = GTextNodeType_Custom;
|
|
custom_node.callback = prv_draw_custom_clip;
|
|
|
|
// Clipping off
|
|
s_data.gcontext.draw_state.clip_box = DISP_FRAME;
|
|
s_data.clip_box = DISP_FRAME;
|
|
graphics_text_node_draw(&custom_node.node, ctx, &TEST_CLIP_BOX, NULL, NULL);
|
|
cl_assert_equal_grect(ctx->draw_state.clip_box, DISP_FRAME);
|
|
|
|
// Clipping on
|
|
custom_node.node.clip = true;
|
|
s_data.gcontext.draw_state.clip_box = DISP_FRAME;
|
|
s_data.clip_box = TEST_CLIP_BOX;
|
|
graphics_text_node_draw(&custom_node.node, ctx, &TEST_CLIP_BOX, NULL, NULL);
|
|
cl_assert_equal_grect(ctx->draw_state.clip_box, DISP_FRAME);
|
|
}
|