mirror of
https://github.com/google/pebble.git
synced 2025-03-21 11:21:21 +00:00
815 lines
28 KiB
C
815 lines
28 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 "clar.h"
|
|
|
|
#include "applib/graphics/gdraw_command.h"
|
|
#include "applib/graphics/gdraw_command_list.h"
|
|
#include "applib/graphics/gdraw_command_image.h"
|
|
#include "applib/graphics/gdraw_command_private.h"
|
|
|
|
#include "applib/graphics/gtypes.h"
|
|
#include "applib/graphics/graphics.h"
|
|
#include "applib/graphics/graphics_line.h"
|
|
#include "applib/graphics/gpath.h"
|
|
|
|
#include <string.h>
|
|
|
|
#include "stubs_applib_resource.h"
|
|
#include "stubs_app_state.h"
|
|
#include "stubs_compiled_with_legacy2_sdk.h"
|
|
#include "stubs_heap.h"
|
|
#include "stubs_memory_layout.h"
|
|
#include "stubs_passert.h"
|
|
#include "stubs_pbl_malloc.h"
|
|
#include "stubs_resources.h"
|
|
#include "stubs_syscalls.h"
|
|
|
|
extern size_t prv_get_list_max_command_size(GDrawCommandList *command_list);
|
|
|
|
static GColor s_fill_color;
|
|
static GColor s_stroke_color;
|
|
static uint8_t s_stroke_width;
|
|
static uint16_t s_path_num_points;
|
|
static GPoint *s_stroke_points = NULL;
|
|
static GPoint *s_fill_points = NULL;
|
|
static bool s_path_open;
|
|
static uint16_t s_radius;
|
|
|
|
struct PreciseLine {
|
|
GPointPrecise p0;
|
|
GPointPrecise p1;
|
|
} *s_precise_lines = NULL;
|
|
static int s_num_precise_lines;
|
|
|
|
static int s_path_stroke_count;
|
|
static int s_path_stroke_precise_count;
|
|
static int s_path_fill_count;
|
|
static int s_path_fill_precise_count;
|
|
static int s_circle_stroke_count;
|
|
static int s_circle_fill_count;
|
|
static GPoint s_offset;
|
|
|
|
static GPoint *prv_copy_points(GPoint *points, uint16_t num_points, GPoint offset) {
|
|
s_path_num_points = num_points;
|
|
GPoint *copied_points = malloc(num_points * sizeof(GPoint));
|
|
cl_assert(copied_points != NULL);
|
|
for (int i = 0; i < num_points; i++) {
|
|
copied_points[i] = gpoint_add(points[i], offset);
|
|
}
|
|
return copied_points;
|
|
}
|
|
|
|
static bool prv_compare_points(GPoint *a, GPoint *b, uint16_t num_points) {
|
|
return (memcmp(a, b, sizeof(GPoint) * num_points) == 0);
|
|
}
|
|
|
|
// Stubs
|
|
void graphics_context_set_stroke_color(GContext* ctx, GColor color) {
|
|
s_stroke_color = color;
|
|
}
|
|
|
|
void graphics_context_set_fill_color(GContext* ctx, GColor color) {
|
|
s_fill_color = color;
|
|
}
|
|
|
|
void graphics_context_set_antialiased(GContext *ctx, bool enable) {
|
|
|
|
}
|
|
|
|
void graphics_context_set_stroke_width(GContext* ctx, uint8_t stroke_width) {
|
|
s_stroke_width = stroke_width;
|
|
}
|
|
|
|
void gpath_draw_stroke(GContext* ctx, GPath* path, bool open) {
|
|
s_stroke_points = prv_copy_points(path->points, path->num_points, s_offset);
|
|
s_path_open = open;
|
|
s_path_stroke_count++;
|
|
}
|
|
|
|
void gpath_fill_precise_internal(GContext *ctx, GPointPrecise *points, size_t num_points) {
|
|
s_fill_points = prv_copy_points((GPoint*)points, num_points, s_offset);
|
|
s_path_fill_precise_count++;
|
|
}
|
|
|
|
void gpath_draw_filled(GContext* ctx, GPath *path) {
|
|
s_fill_points = prv_copy_points(path->points, path->num_points, s_offset);
|
|
s_path_fill_count++;
|
|
}
|
|
|
|
void gpath_draw_outline_precise_internal(GContext *ctx, GPointPrecise *points, size_t num_points,
|
|
bool open) {
|
|
s_stroke_points = prv_copy_points((GPoint*)points, num_points, s_offset);
|
|
s_path_open = open;
|
|
s_path_stroke_precise_count++;
|
|
}
|
|
|
|
void graphics_draw_circle(GContext* ctx, GPoint p, uint16_t radius) {
|
|
s_stroke_points = prv_copy_points(&p, 1, s_offset);
|
|
s_radius = radius;
|
|
s_circle_stroke_count++;
|
|
}
|
|
|
|
void graphics_fill_circle(GContext* ctx, GPoint p, uint16_t radius) {
|
|
s_fill_points = prv_copy_points(&p, 1, s_offset);
|
|
s_radius = radius;
|
|
s_circle_fill_count++;
|
|
}
|
|
|
|
void graphics_context_move_draw_box(GContext* ctx, GPoint offset) {
|
|
s_offset = offset;
|
|
}
|
|
|
|
void graphics_line_draw_precise_stroked(GContext* ctx, GPointPrecise p0, GPointPrecise p1) {
|
|
s_precise_lines = realloc(s_precise_lines,
|
|
(s_num_precise_lines + 1) * sizeof(*s_precise_lines));
|
|
|
|
s_precise_lines[s_num_precise_lines].p0 = p0;
|
|
s_precise_lines[s_num_precise_lines].p1 = p1;
|
|
s_num_precise_lines++;
|
|
}
|
|
|
|
|
|
void prv_reset(void) {
|
|
s_fill_color = GColorClear;
|
|
s_stroke_color = GColorClear;
|
|
s_stroke_width = 0;
|
|
s_path_num_points = 0;
|
|
if (s_stroke_points) {
|
|
free(s_stroke_points);
|
|
s_stroke_points = NULL;
|
|
}
|
|
if (s_fill_points) {
|
|
free(s_fill_points);
|
|
s_fill_points = NULL;
|
|
}
|
|
s_path_open = false;
|
|
s_radius = 0;
|
|
|
|
s_path_stroke_count = 0;
|
|
s_path_stroke_precise_count = 0;
|
|
s_path_fill_count = 0;
|
|
s_path_fill_precise_count = 0;
|
|
s_circle_stroke_count = 0;
|
|
s_circle_fill_count = 0;
|
|
s_offset = (GPoint){ 0 };
|
|
|
|
if (s_precise_lines) {
|
|
free(s_precise_lines);
|
|
s_precise_lines = NULL;
|
|
}
|
|
s_num_precise_lines = 0;
|
|
}
|
|
|
|
// setup and teardown
|
|
void test_gdraw_command__initialize(void) {
|
|
prv_reset();
|
|
}
|
|
|
|
void test_gdraw_command__cleanup(void) {
|
|
if (s_stroke_points) {
|
|
free(s_stroke_points);
|
|
s_stroke_points = NULL;
|
|
}
|
|
if (s_fill_points) {
|
|
free(s_fill_points);
|
|
s_fill_points = NULL;
|
|
}
|
|
if (s_precise_lines) {
|
|
free(s_precise_lines);
|
|
s_precise_lines = NULL;
|
|
}
|
|
}
|
|
|
|
// tests
|
|
void test_gdraw_command__draw_command_stroke(void) {
|
|
GDrawCommand *command = malloc(sizeof(GDrawCommand) + (sizeof(GPoint) * 2));
|
|
*command = (GDrawCommand){
|
|
.type = GDrawCommandTypePath,
|
|
.hidden = false,
|
|
.stroke_color = GColorRed,
|
|
.stroke_width = 1,
|
|
.fill_color = GColorBlue,
|
|
.path_open = false,
|
|
.num_points = 2,
|
|
};
|
|
GPoint points[] = {{ 3, 97 }, {5, 5} };
|
|
memcpy(command->points, points, sizeof(points));
|
|
gdraw_command_draw(NULL, command);
|
|
|
|
cl_assert_equal_i(s_stroke_color.argb, GColorRedARGB8);
|
|
cl_assert_equal_i(s_fill_color.argb, GColorBlueARGB8);
|
|
cl_assert_equal_i(s_stroke_width, 1);
|
|
cl_assert_equal_i(s_path_num_points, 2);
|
|
cl_assert_equal_b(s_path_open, false);
|
|
cl_assert_equal_i(s_path_fill_count, 1);
|
|
cl_assert_equal_i(s_path_stroke_count, 1);
|
|
cl_assert(prv_compare_points(points, s_stroke_points, s_path_num_points));
|
|
cl_assert(prv_compare_points(points, s_fill_points, s_path_num_points));
|
|
|
|
prv_reset();
|
|
// set stroke width to zero - fill should be drawn, but not outline
|
|
gdraw_command_set_stroke_width(command, 0);
|
|
gdraw_command_draw(NULL, command);
|
|
cl_assert_equal_i(s_stroke_color.argb, GColorClearARGB8);
|
|
cl_assert_equal_i(s_fill_color.argb, GColorBlueARGB8);
|
|
cl_assert_equal_i(s_stroke_width, 0);
|
|
cl_assert_equal_i(s_path_num_points, 2);
|
|
cl_assert_equal_b(s_path_open, false);
|
|
cl_assert_equal_i(s_path_fill_count, 1);
|
|
cl_assert_equal_i(s_path_stroke_count, 0);
|
|
cl_assert(prv_compare_points(points, s_fill_points, s_path_num_points));
|
|
cl_assert_equal_p(s_stroke_points, NULL);
|
|
|
|
prv_reset();
|
|
// make fill color transparent (nothing should be drawn because the stroke width is zero and the
|
|
// fill is transparent
|
|
GColor color = gdraw_command_get_fill_color(command);
|
|
color.a = 0;
|
|
gdraw_command_set_fill_color(command, color);
|
|
gdraw_command_draw(NULL, command);
|
|
cl_assert_equal_i(s_stroke_color.argb, GColorClearARGB8);
|
|
cl_assert_equal_i(s_fill_color.argb, GColorClearARGB8);
|
|
cl_assert_equal_i(s_stroke_width, 0);
|
|
cl_assert_equal_i(s_path_num_points, 0);
|
|
cl_assert_equal_b(s_path_open, false);
|
|
cl_assert_equal_i(s_path_fill_count, 0);
|
|
cl_assert_equal_i(s_path_stroke_count, 0);
|
|
cl_assert_equal_p(s_stroke_points, NULL);
|
|
cl_assert_equal_p(s_fill_points, NULL);
|
|
|
|
prv_reset();
|
|
// set stroke width to non-zero value. stroke should be drawn, but no fill
|
|
gdraw_command_set_stroke_width(command, 2);
|
|
gdraw_command_draw(NULL, command);
|
|
cl_assert_equal_i(s_stroke_color.argb, GColorRedARGB8);
|
|
cl_assert_equal_i(s_fill_color.argb, GColorClearARGB8);
|
|
cl_assert_equal_i(s_stroke_width, 2);
|
|
cl_assert_equal_i(s_path_num_points, 2);
|
|
cl_assert_equal_b(s_path_open, false);
|
|
cl_assert_equal_i(s_path_fill_count, 0);
|
|
cl_assert_equal_i(s_path_stroke_count, 1);
|
|
cl_assert(prv_compare_points(points, s_stroke_points, s_path_num_points));
|
|
cl_assert_equal_p(s_fill_points, NULL);
|
|
|
|
prv_reset();
|
|
// set stroke color to be transparent and restore fill - fill should be drawn, but no outline
|
|
// should be drawn
|
|
gdraw_command_set_fill_color(command, GColorGreen);
|
|
color = gdraw_command_get_stroke_color(command);
|
|
color.a = 0;
|
|
gdraw_command_set_stroke_color(command, color);
|
|
gdraw_command_draw(NULL, command);
|
|
cl_assert_equal_i(s_stroke_color.argb, GColorClearARGB8);
|
|
cl_assert_equal_i(s_fill_color.argb, GColorGreenARGB8);
|
|
cl_assert_equal_i(s_stroke_width, 0);
|
|
cl_assert_equal_i(s_path_num_points, 2);
|
|
cl_assert_equal_b(s_path_open, false);
|
|
cl_assert_equal_i(s_path_fill_count, 1);
|
|
cl_assert_equal_i(s_path_stroke_count, 0);
|
|
cl_assert_equal_p(s_stroke_points, NULL);
|
|
cl_assert(prv_compare_points(points, s_fill_points, s_path_num_points));
|
|
|
|
prv_reset();
|
|
// restore stroke color and change both points
|
|
gdraw_command_set_stroke_color(command, GColorPurple);
|
|
GPoint points2[] = { { 23, 45 }, { 67, 13} };
|
|
gdraw_command_set_point(command, 0, points2[0]);
|
|
gdraw_command_set_point(command, 1, points2[1]);
|
|
gdraw_command_draw(NULL, command);
|
|
cl_assert_equal_i(s_stroke_color.argb, GColorPurpleARGB8);
|
|
cl_assert_equal_i(s_fill_color.argb, GColorGreenARGB8);
|
|
cl_assert_equal_i(s_stroke_width, 2);
|
|
cl_assert_equal_i(s_path_num_points, 2);
|
|
cl_assert_equal_b(s_path_open, false);
|
|
cl_assert_equal_i(s_path_fill_count, 1);
|
|
cl_assert_equal_i(s_path_stroke_count, 1);
|
|
cl_assert(prv_compare_points(points2, s_stroke_points, s_path_num_points));
|
|
cl_assert(prv_compare_points(points2, s_fill_points, s_path_num_points));
|
|
|
|
prv_reset();
|
|
// set path to be open
|
|
gdraw_command_set_path_open(command, true);
|
|
gdraw_command_draw(NULL, command);
|
|
cl_assert_equal_i(s_stroke_color.argb, GColorPurpleARGB8);
|
|
cl_assert_equal_i(s_fill_color.argb, GColorGreenARGB8);
|
|
cl_assert_equal_i(s_stroke_width, 2);
|
|
cl_assert_equal_i(s_path_num_points, 2);
|
|
cl_assert_equal_b(s_path_open, true);
|
|
cl_assert_equal_i(s_path_fill_count, 1);
|
|
cl_assert_equal_i(s_path_stroke_count, 1);
|
|
cl_assert(prv_compare_points(points2, s_stroke_points, s_path_num_points));
|
|
cl_assert(prv_compare_points(points2, s_fill_points, s_path_num_points));
|
|
|
|
prv_reset();
|
|
// set command to be hidden - nothing should be drawn
|
|
gdraw_command_set_hidden(command, true);
|
|
cl_assert_equal_i(s_stroke_color.argb, GColorClearARGB8);
|
|
cl_assert_equal_i(s_fill_color.argb, GColorClearARGB8);
|
|
cl_assert_equal_i(s_stroke_width, 0);
|
|
cl_assert_equal_i(s_path_num_points, 0);
|
|
cl_assert_equal_b(s_path_open, false);
|
|
cl_assert_equal_i(s_path_fill_count, 0);
|
|
cl_assert_equal_i(s_path_stroke_count, 0);
|
|
cl_assert_equal_p(s_stroke_points, NULL);
|
|
cl_assert_equal_p(s_fill_points, NULL);
|
|
|
|
free(command);
|
|
}
|
|
|
|
void test_gdraw_command__draw_precise_path(void) {
|
|
GDrawCommand *command = malloc(sizeof(GDrawCommand) + (sizeof(GPoint) * 3 ));
|
|
*command = (GDrawCommand){
|
|
.type = GDrawCommandTypePrecisePath,
|
|
.hidden = false,
|
|
.stroke_color = GColorRed,
|
|
.stroke_width = 1,
|
|
.fill_color = GColorBlue,
|
|
.path_open = false,
|
|
.num_points = 3,
|
|
};
|
|
GPointPrecise points[] = {
|
|
{ .x.raw_value = 8, .y.raw_value = 17 },
|
|
{ .x.raw_value = 4, .y.raw_value = 16 },
|
|
{ .x.raw_value = 2,.y.raw_value = 7 }
|
|
};
|
|
memcpy(command->precise_points, points, sizeof(points));
|
|
gdraw_command_draw(NULL, command);
|
|
|
|
cl_assert_equal_i(1, s_path_fill_precise_count);
|
|
cl_assert(prv_compare_points((GPoint*)points, s_fill_points, s_path_num_points));
|
|
|
|
cl_assert_equal_i(1, s_path_stroke_precise_count);
|
|
cl_assert_equal_b(false, s_path_open);
|
|
cl_assert(prv_compare_points((GPoint*)points, s_stroke_points, s_path_num_points));
|
|
|
|
prv_reset();
|
|
// change to open path and ensure that only draws 2 lines
|
|
command->path_open = true;
|
|
gdraw_command_draw(NULL, command);
|
|
cl_assert_equal_i(1, s_path_stroke_precise_count);
|
|
cl_assert_equal_b(true, s_path_open);
|
|
cl_assert(prv_compare_points((GPoint*)points, s_stroke_points, s_path_num_points));
|
|
|
|
free(command);
|
|
}
|
|
|
|
void test_gdraw_command__draw_circle(void) {
|
|
GDrawCommand *command = malloc(sizeof(GDrawCommand) + sizeof(GPoint));
|
|
*command = (GDrawCommand){
|
|
.type = GDrawCommandTypeCircle,
|
|
.hidden = false,
|
|
.stroke_color = GColorGreen,
|
|
.stroke_width = 1,
|
|
.fill_color = GColorOrange,
|
|
.radius = 300,
|
|
.num_points = 1,
|
|
};
|
|
GPoint center = { 15, 17 };
|
|
command->points[0] = center;
|
|
gdraw_command_draw(NULL, command);
|
|
|
|
cl_assert_equal_i(s_stroke_color.argb, GColorGreenARGB8);
|
|
cl_assert_equal_i(s_fill_color.argb, GColorOrangeARGB8);
|
|
cl_assert_equal_i(s_stroke_width, 1);
|
|
cl_assert_equal_i(s_path_num_points, 1);
|
|
cl_assert_equal_b(s_radius, 300);
|
|
cl_assert_equal_i(s_circle_fill_count, 1);
|
|
cl_assert_equal_i(s_circle_stroke_count, 1);
|
|
cl_assert(prv_compare_points(¢er, s_stroke_points, s_path_num_points));
|
|
cl_assert(prv_compare_points(¢er, s_fill_points, s_path_num_points));
|
|
|
|
prv_reset();
|
|
// set stroke width to zero - fill should be drawn, but not outline
|
|
gdraw_command_set_stroke_width(command, 0);
|
|
gdraw_command_draw(NULL, command);
|
|
cl_assert_equal_i(s_stroke_color.argb, GColorClearARGB8);
|
|
cl_assert_equal_i(s_fill_color.argb, GColorOrangeARGB8);
|
|
cl_assert_equal_i(s_stroke_width, 0);
|
|
cl_assert_equal_i(s_path_num_points, 1);
|
|
cl_assert_equal_b(s_radius, 300);
|
|
cl_assert_equal_i(s_circle_fill_count, 1);
|
|
cl_assert_equal_i(s_circle_stroke_count, 0);
|
|
cl_assert_equal_p(s_stroke_points, NULL);
|
|
cl_assert(prv_compare_points(¢er, s_fill_points, s_path_num_points));
|
|
|
|
prv_reset();
|
|
// make fill color transparent (nothing should be drawn because the stroke width is zero and the
|
|
// fill is transparent
|
|
GColor color = gdraw_command_get_fill_color(command);
|
|
color.a = 0;
|
|
gdraw_command_set_fill_color(command, color);
|
|
gdraw_command_draw(NULL, command);
|
|
cl_assert_equal_i(s_stroke_color.argb, GColorClearARGB8);
|
|
cl_assert_equal_i(s_fill_color.argb, GColorClearARGB8);
|
|
cl_assert_equal_i(s_stroke_width, 0);
|
|
cl_assert_equal_i(s_path_num_points, 0);
|
|
cl_assert_equal_b(s_radius, 0);
|
|
cl_assert_equal_i(s_circle_fill_count, 0);
|
|
cl_assert_equal_i(s_circle_stroke_count, 0);
|
|
cl_assert_equal_p(s_stroke_points, NULL);
|
|
cl_assert_equal_p(s_fill_points, NULL);
|
|
|
|
prv_reset();
|
|
// set stroke width to non-zero value. stroke should be drawn, but no fill
|
|
gdraw_command_set_stroke_width(command, 2);
|
|
gdraw_command_draw(NULL, command);
|
|
cl_assert_equal_i(s_stroke_color.argb, GColorGreenARGB8);
|
|
cl_assert_equal_i(s_fill_color.argb, GColorClearARGB8);
|
|
cl_assert_equal_i(s_stroke_width, 2);
|
|
cl_assert_equal_i(s_path_num_points, 1);
|
|
cl_assert_equal_b(s_radius, 300);
|
|
cl_assert_equal_i(s_circle_fill_count, 0);
|
|
cl_assert_equal_i(s_circle_stroke_count, 1);
|
|
cl_assert(prv_compare_points(¢er, s_stroke_points, s_path_num_points));
|
|
cl_assert_equal_p(s_fill_points, NULL);
|
|
|
|
prv_reset();
|
|
// set stroke color to be transparent and restore fill - fill should be drawn, but no outline
|
|
// should be drawn
|
|
gdraw_command_set_fill_color(command, GColorRed);
|
|
color = gdraw_command_get_stroke_color(command);
|
|
color.a = 0;
|
|
gdraw_command_set_stroke_color(command, color);
|
|
gdraw_command_draw(NULL, command);
|
|
cl_assert_equal_i(s_stroke_color.argb, GColorClearARGB8);
|
|
cl_assert_equal_i(s_fill_color.argb, GColorRedARGB8);
|
|
cl_assert_equal_i(s_stroke_width, 0);
|
|
cl_assert_equal_i(s_path_num_points, 1);
|
|
cl_assert_equal_b(s_path_open, false);
|
|
cl_assert_equal_i(s_circle_fill_count, 1);
|
|
cl_assert_equal_i(s_circle_stroke_count, 0);
|
|
cl_assert_equal_p(s_stroke_points, NULL);
|
|
cl_assert(prv_compare_points(¢er, s_fill_points, s_path_num_points));
|
|
|
|
prv_reset();
|
|
// restore stroke color and set radius to zero - only a stroke should be drawn
|
|
gdraw_command_set_stroke_color(command, GColorPurple);
|
|
gdraw_command_set_radius(command, 0);
|
|
gdraw_command_draw(NULL, command);
|
|
cl_assert_equal_i(s_stroke_color.argb, GColorPurpleARGB8);
|
|
cl_assert_equal_i(s_fill_color.argb, GColorClearARGB8);
|
|
cl_assert_equal_i(s_stroke_width, 2);
|
|
cl_assert_equal_i(s_path_num_points, 1);
|
|
cl_assert_equal_b(s_radius, 0);
|
|
cl_assert_equal_i(s_circle_fill_count, 0);
|
|
cl_assert_equal_i(s_circle_stroke_count, 1);
|
|
cl_assert(prv_compare_points(¢er, s_stroke_points, s_path_num_points));
|
|
cl_assert_equal_p(s_fill_points, NULL);
|
|
|
|
prv_reset();
|
|
// restore radius and set hidden - nothing should be drawn
|
|
gdraw_command_set_radius(command, 300);
|
|
gdraw_command_set_hidden(command, true);
|
|
gdraw_command_draw(NULL, command);
|
|
cl_assert_equal_i(s_stroke_color.argb, GColorClearARGB8);
|
|
cl_assert_equal_i(s_fill_color.argb, GColorClearARGB8);
|
|
cl_assert_equal_i(s_stroke_width, 0);
|
|
cl_assert_equal_i(s_path_num_points, 0);
|
|
cl_assert_equal_b(s_radius, 0);
|
|
cl_assert_equal_i(s_circle_fill_count, 0);
|
|
cl_assert_equal_i(s_circle_stroke_count, 0);
|
|
cl_assert_equal_p(s_stroke_points, NULL);
|
|
cl_assert_equal_p(s_fill_points, NULL);
|
|
|
|
free(command);
|
|
}
|
|
|
|
static GDrawCommandList *prv_create_command_list_3(void) {
|
|
GDrawCommandList *command_list = malloc(sizeof(GDrawCommandList) + (3 * sizeof(GDrawCommand)) +
|
|
(sizeof(GPoint) * 6));
|
|
*command_list = (GDrawCommandList) {
|
|
.num_commands = 3
|
|
};
|
|
GDrawCommand *command;
|
|
command = gdraw_command_list_get_command(command_list, 0);
|
|
*command = (GDrawCommand) {
|
|
.type = GDrawCommandTypePath,
|
|
.hidden = false,
|
|
.stroke_color = GColorRed,
|
|
.stroke_width = 1,
|
|
.fill_color = GColorBlue,
|
|
.path_open = false,
|
|
.num_points = 2,
|
|
};
|
|
GPoint points1[] = { { 3, 97 }, {5, 5} };
|
|
memcpy(command_list->commands[0].points, points1, sizeof(points1));
|
|
|
|
command = gdraw_command_list_get_command(command_list, 1);
|
|
*command = (GDrawCommand) {
|
|
.type = GDrawCommandTypeCircle,
|
|
.hidden = false,
|
|
.stroke_color = GColorGreen,
|
|
.stroke_width = 1,
|
|
.fill_color = GColorOrange,
|
|
.radius = 300,
|
|
.num_points = 1,
|
|
};
|
|
command->points[0] = (GPoint) { 1, 2 };
|
|
|
|
command = gdraw_command_list_get_command(command_list, 2);
|
|
*command = (GDrawCommand) {
|
|
.type = GDrawCommandTypePath,
|
|
.hidden = false,
|
|
.stroke_color = GColorGreen,
|
|
.stroke_width = 1,
|
|
.fill_color = GColorPurple,
|
|
.path_open = false,
|
|
.num_points = 3,
|
|
};
|
|
GPoint points2[] = { { 6, 7 }, {5, 5}, { 0, 0 } };
|
|
memcpy(command->points, points2, sizeof(points2));
|
|
|
|
return command_list;
|
|
}
|
|
|
|
void test_gdraw_command__draw_command_list(void) {
|
|
GDrawCommandList *command_list = malloc(sizeof(GDrawCommandList) + sizeof(GDrawCommand) +
|
|
(sizeof(GPoint) * 2));
|
|
*command_list = (GDrawCommandList) {
|
|
.num_commands = 1
|
|
};
|
|
command_list->commands[0] = (GDrawCommand) {
|
|
.type = GDrawCommandTypePath,
|
|
.hidden = false,
|
|
.stroke_color = GColorRed,
|
|
.stroke_width = 1,
|
|
.fill_color = GColorBlue,
|
|
.path_open = false,
|
|
.num_points = 2,
|
|
};
|
|
GPoint points1[] = { { 3, 97 }, {5, 5} };
|
|
memcpy(command_list->commands[0].points, points1, sizeof(points1));
|
|
|
|
GContext *ctx = (GContext *)123; // just a fake internal guard != NULL
|
|
|
|
gdraw_command_list_draw(ctx, command_list);
|
|
cl_assert_equal_i(s_path_stroke_count, 1);
|
|
cl_assert_equal_i(s_path_fill_count, 1);
|
|
cl_assert_equal_i(s_circle_stroke_count, 0);
|
|
cl_assert_equal_i(s_circle_fill_count, 0);
|
|
|
|
prv_reset();
|
|
free(command_list);
|
|
|
|
command_list = prv_create_command_list_3();
|
|
|
|
gdraw_command_list_draw(ctx, command_list);
|
|
cl_assert_equal_i(s_path_stroke_count, 2);
|
|
cl_assert_equal_i(s_path_fill_count, 2);
|
|
cl_assert_equal_i(s_circle_stroke_count, 1);
|
|
cl_assert_equal_i(s_circle_fill_count, 1);
|
|
|
|
prv_reset();
|
|
gdraw_command_list_get_command(command_list, 2)->hidden = true;
|
|
gdraw_command_list_draw(ctx, command_list);
|
|
cl_assert_equal_i(s_path_stroke_count, 1);
|
|
cl_assert_equal_i(s_path_fill_count, 1);
|
|
cl_assert_equal_i(s_circle_stroke_count, 1);
|
|
cl_assert_equal_i(s_circle_fill_count, 1);
|
|
|
|
prv_reset();
|
|
gdraw_command_list_get_command(command_list, 0)->hidden = true;
|
|
gdraw_command_list_draw(ctx, command_list);
|
|
cl_assert_equal_i(s_path_stroke_count, 0);
|
|
cl_assert_equal_i(s_path_fill_count, 0);
|
|
cl_assert_equal_i(s_circle_stroke_count, 1);
|
|
cl_assert_equal_i(s_circle_fill_count, 1);
|
|
|
|
prv_reset();
|
|
gdraw_command_list_get_command(command_list, 1)->hidden = true;
|
|
gdraw_command_list_draw(ctx, command_list);
|
|
cl_assert_equal_i(s_path_stroke_count, 0);
|
|
cl_assert_equal_i(s_path_fill_count, 0);
|
|
cl_assert_equal_i(s_circle_stroke_count, 0);
|
|
cl_assert_equal_i(s_circle_fill_count, 0);
|
|
|
|
free(command_list);
|
|
}
|
|
|
|
void test_gdraw_command__validate_list(void) {
|
|
GDrawCommandList *command_list = prv_create_command_list_3();
|
|
size_t size = sizeof(GDrawCommandList) + (3 * sizeof(GDrawCommand)) +
|
|
(sizeof(GPoint) * 6);
|
|
cl_assert(gdraw_command_list_validate(command_list, size));
|
|
|
|
command_list->num_commands = 4;
|
|
cl_assert(!gdraw_command_list_validate(command_list, size));
|
|
command_list->num_commands = 3;
|
|
GDrawCommand *command = gdraw_command_list_get_command(command_list, 0);
|
|
command->num_points = 0;
|
|
cl_assert(!gdraw_command_list_validate(command_list, size));
|
|
command->num_points = 2;
|
|
command = gdraw_command_list_get_command(command_list, 2);
|
|
command->num_points = 4;
|
|
cl_assert(!gdraw_command_list_validate(command_list, size));
|
|
command->num_points = 3;
|
|
command->type = GDrawCommandTypeCircle;
|
|
cl_assert(!gdraw_command_list_validate(command_list, size));
|
|
command->type = GDrawCommandTypePrecisePath;
|
|
cl_assert(gdraw_command_list_validate(command_list, size));
|
|
|
|
free(command_list);
|
|
}
|
|
|
|
void test_gdraw_command__validate_image(void) {
|
|
size_t size = sizeof(GDrawCommandImage) + (3 * sizeof(GDrawCommand)) +
|
|
(sizeof(GPoint) * 6);
|
|
|
|
GDrawCommandImage *image = malloc(size);
|
|
GDrawCommandList *command_list = prv_create_command_list_3();
|
|
memcpy(&image->command_list, command_list, sizeof(GDrawCommandList) + (3 * sizeof(GDrawCommand)) +
|
|
(sizeof(GPoint) * 6));
|
|
free(command_list);
|
|
|
|
image->version = 1;
|
|
image->size = GSize(20, 20);
|
|
cl_assert(gdraw_command_image_validate(image, size));
|
|
cl_assert(!gdraw_command_image_validate(image, size - 1));
|
|
cl_assert(!gdraw_command_image_validate(image, size + 1));
|
|
|
|
cl_assert_equal_i(size, gdraw_command_image_get_data_size(image));
|
|
|
|
image->version = 2;
|
|
cl_assert(!gdraw_command_image_validate(image, size));
|
|
|
|
free(image);
|
|
}
|
|
|
|
void test_gdraw_command__clone_image(void) {
|
|
cl_assert_equal_p(gdraw_command_image_clone(NULL), NULL);
|
|
|
|
size_t size = sizeof(GDrawCommandImage) + (3 * sizeof(GDrawCommand)) +
|
|
(sizeof(GPoint) * 6);
|
|
|
|
GDrawCommandImage *image = malloc(size);
|
|
memset(image, 0, size);
|
|
|
|
GDrawCommandList *command_list = prv_create_command_list_3();
|
|
memcpy(&image->command_list, command_list, sizeof(GDrawCommandList) + (3 * sizeof(GDrawCommand)) +
|
|
(sizeof(GPoint) * 6));
|
|
free(command_list);
|
|
|
|
image->version = 1;
|
|
image->size = GSize(20, 20);
|
|
|
|
GDrawCommandImage *clone = gdraw_command_image_clone(image);
|
|
cl_assert(clone != image);
|
|
cl_assert_equal_i(gdraw_command_image_get_data_size(clone), size);
|
|
cl_assert_equal_i(0, memcmp(clone, image, size));
|
|
|
|
free(clone);
|
|
free(image);
|
|
}
|
|
|
|
void test_gdraw_command__draw_image(void) {
|
|
GDrawCommandImage *image = malloc(sizeof(GDrawCommandImage) + sizeof(GDrawCommand) +
|
|
(sizeof(GPoint) * 2));
|
|
GDrawCommandList *command_list = &image->command_list;
|
|
*command_list = (GDrawCommandList) {
|
|
.num_commands = 1
|
|
};
|
|
GDrawCommand *command;
|
|
command = gdraw_command_list_get_command(command_list, 0);
|
|
*command = (GDrawCommand) {
|
|
.type = GDrawCommandTypePath,
|
|
.hidden = false,
|
|
.stroke_color = GColorRed,
|
|
.stroke_width = 1,
|
|
.fill_color = GColorBlue,
|
|
.path_open = true,
|
|
.num_points = 2,
|
|
};
|
|
GPoint points[] = {{ 6, 1 }, {5, -5} };
|
|
memcpy(command_list->commands[0].points, points, sizeof(points));
|
|
|
|
GContext *ctx = (GContext *)123; // just a fake internal guard != NULL
|
|
|
|
gdraw_command_image_draw(ctx, image, GPoint(0, 0));
|
|
cl_assert_equal_i(s_path_num_points, 2);
|
|
cl_assert(prv_compare_points(points, s_stroke_points, s_path_num_points));
|
|
cl_assert(prv_compare_points(points, s_fill_points, s_path_num_points));
|
|
|
|
prv_reset();
|
|
gdraw_command_image_draw(ctx, image, GPoint(-1, 1));
|
|
cl_assert_equal_i(s_path_num_points, 2);
|
|
points[0] = GPoint(5, 2);
|
|
points[1] = GPoint(4, -4);
|
|
cl_assert(prv_compare_points(points, s_stroke_points, s_path_num_points));
|
|
cl_assert(prv_compare_points(points, s_fill_points, s_path_num_points));
|
|
|
|
free(image);
|
|
}
|
|
|
|
void test_gdraw_command__draw_frame(void) {
|
|
GDrawCommandFrame *frame = malloc(sizeof(GDrawCommandFrame) + sizeof(GDrawCommand) +
|
|
(sizeof(GPoint) * 2));
|
|
GDrawCommandList *command_list = &frame->command_list;
|
|
*command_list = (GDrawCommandList) {
|
|
.num_commands = 1
|
|
};
|
|
GDrawCommand *command = gdraw_command_list_get_command(command_list, 0);
|
|
*command = (GDrawCommand) {
|
|
.type = GDrawCommandTypePath,
|
|
.hidden = false,
|
|
.stroke_color = GColorRed,
|
|
.stroke_width = 1,
|
|
.fill_color = GColorBlue,
|
|
.path_open = true,
|
|
.num_points = 2,
|
|
};
|
|
GPoint points[] = {{ 1, 1 }, {2, -2} };
|
|
memcpy(command_list->commands[0].points, points, sizeof(points));
|
|
|
|
GContext *ctx = (GContext *)123; // just a fake internal guard != NULL
|
|
|
|
gdraw_command_frame_draw(ctx, NULL, frame, GPoint(0, 0));
|
|
cl_assert_equal_i(s_path_num_points, 2);
|
|
cl_assert(prv_compare_points(points, s_stroke_points, s_path_num_points));
|
|
cl_assert(prv_compare_points(points, s_fill_points, s_path_num_points));
|
|
|
|
prv_reset();
|
|
gdraw_command_frame_draw(ctx, NULL, frame, GPoint(-1, 1));
|
|
cl_assert_equal_i(s_path_num_points, 2);
|
|
points[0] = GPoint(0, 2);
|
|
points[1] = GPoint(1, -1);
|
|
cl_assert(prv_compare_points(points, s_stroke_points, s_path_num_points));
|
|
cl_assert(prv_compare_points(points, s_fill_points, s_path_num_points));
|
|
|
|
free(frame);
|
|
}
|
|
|
|
static int s_iterations = 0;
|
|
static bool prv_iterate(GDrawCommand *command, uint32_t index, void *context) {
|
|
s_iterations++;
|
|
return true;
|
|
}
|
|
|
|
void test_gdraw_command__iterate(void) {
|
|
GDrawCommandList *command_list = prv_create_command_list_3();
|
|
void *end = gdraw_command_list_iterate_private(command_list, prv_iterate, NULL);
|
|
cl_assert_equal_i(s_iterations, 3);
|
|
GDrawCommand *command = gdraw_command_list_get_command(command_list, 2);
|
|
void *expected_end = command->points + command->num_points;
|
|
cl_assert_equal_p(end, expected_end);
|
|
|
|
free(command_list);
|
|
}
|
|
|
|
typedef struct {
|
|
GDrawCommandProcessor processor;
|
|
GColor stroke_color;
|
|
} SetStrokeColorProcessor;
|
|
|
|
static void prv_set_stroke_color(GDrawCommandProcessor *processor,
|
|
GDrawCommand *processed_command,
|
|
const size_t processed_command_max_size,
|
|
const GDrawCommandList* list,
|
|
const GDrawCommand *command) {
|
|
SetStrokeColorProcessor *stroke_processor = (SetStrokeColorProcessor *)processor;
|
|
gdraw_command_set_stroke_color(processed_command, stroke_processor->stroke_color);
|
|
}
|
|
|
|
void test_gdraw_command__draw_command_list_processed(void) {
|
|
GDrawCommandList *command_list = prv_create_command_list_3();
|
|
GColor stroke_color = GColorTiffanyBlue;
|
|
SetStrokeColorProcessor stroke_processor = {
|
|
.processor = {
|
|
.command = prv_set_stroke_color,
|
|
},
|
|
.stroke_color = stroke_color,
|
|
};
|
|
|
|
// ctx can't be null pass in random pointer to satisfy function
|
|
GContext ctx;
|
|
gdraw_command_list_draw_processed(&ctx, command_list, (GDrawCommandProcessor *)&stroke_processor);
|
|
cl_assert_equal_i(s_stroke_color.argb, GColorTiffanyBlueARGB8);
|
|
|
|
free(command_list);
|
|
}
|
|
|
|
void test_gdraw_command__get_max_command_size_in_list(void) {
|
|
GDrawCommandList *command_list = prv_create_command_list_3();
|
|
|
|
// The third command in the list is the largest so it's size should be returned by
|
|
// prv_get_list_max_command_size
|
|
cl_assert_equal_i(gdraw_command_get_data_size(gdraw_command_list_get_command(command_list, 2)),
|
|
prv_get_list_max_command_size(command_list));
|
|
|
|
free(command_list);
|
|
}
|
|
|
|
|