mirror of
https://repo.dactyloidae.xyz/Dactyloidae/UXP.git
synced 2026-09-22 16:37:31 +09:00
251 lines
8 KiB
C
251 lines
8 KiB
C
#include <wr_internal.h>
|
|
|
|
static size_t
|
|
wr_image_index(const wr_context* context, uint32_t key)
|
|
{
|
|
size_t i;
|
|
for (i = 0; context && i < context->image_count; ++i)
|
|
if (context->images[i].key == key)
|
|
return i;
|
|
return SIZE_MAX;
|
|
}
|
|
|
|
static size_t
|
|
wr_item_index(const wr_context* context, wr_item_id item)
|
|
{
|
|
size_t i;
|
|
for (i = 0; context && i < context->command_count; ++i)
|
|
if (context->commands[i].active && context->commands[i].item_id == item)
|
|
return i;
|
|
return SIZE_MAX;
|
|
}
|
|
|
|
static int
|
|
wr_rect_contains(wr_rect outer, wr_rect inner)
|
|
{
|
|
return inner.x >= outer.x && inner.y >= outer.y &&
|
|
inner.x + inner.width <= outer.x + outer.width &&
|
|
inner.y + inner.height <= outer.y + outer.height;
|
|
}
|
|
|
|
static int
|
|
wr_append(wr_context* context, wr_item_id item, wr_rect rect, wr_color color,
|
|
uint8_t kind, uint32_t image_key, wr_rect tex_rect)
|
|
{
|
|
wr_rect clip = context->clip_depth
|
|
? context->clip_stack[context->clip_depth - 1] : context->viewport;
|
|
if (!context || !wr_valid_rect(rect) ||
|
|
(kind == WR_PRIMITIVE_IMAGE &&
|
|
(wr_image_index(context, image_key) == SIZE_MAX ||
|
|
tex_rect.width == 0.0f || tex_rect.height == 0.0f)))
|
|
return 0;
|
|
if (!wr_reserve((void**)&context->commands, &context->command_capacity,
|
|
context->command_count + 1, sizeof(*context->commands)))
|
|
return 0;
|
|
if (!item) {
|
|
item = context->next_item_id++;
|
|
if (!item)
|
|
item = context->next_item_id++;
|
|
}
|
|
if (wr_item_index(context, item) != SIZE_MAX)
|
|
return 0;
|
|
context->commands[context->command_count] = (wr_rect_command){
|
|
rect, wr_normalize_color(color), context->transform, clip,
|
|
context->clip_depth ? 1 : 0, kind, 1, image_key, tex_rect, item };
|
|
context->commands[context->command_count].color.a *= context->opacity;
|
|
++context->command_count;
|
|
context->frame_valid = 0;
|
|
return 1;
|
|
}
|
|
|
|
int
|
|
wr_context_register_image(wr_context* context, uint32_t key,
|
|
uint32_t width, uint32_t height)
|
|
{
|
|
size_t index;
|
|
if (!context || !key || !width || !height)
|
|
return 0;
|
|
index = wr_image_index(context, key);
|
|
if (index != SIZE_MAX) {
|
|
context->images[index].width = width;
|
|
context->images[index].height = height;
|
|
return 1;
|
|
}
|
|
if (!wr_reserve((void**)&context->images, &context->image_capacity,
|
|
context->image_count + 1, sizeof(*context->images)))
|
|
return 0;
|
|
context->images[context->image_count++] = (wr_image_resource){ key, width, height };
|
|
return 1;
|
|
}
|
|
|
|
void
|
|
wr_context_unregister_image(wr_context* context, uint32_t key)
|
|
{
|
|
size_t index = wr_image_index(context, key);
|
|
if (index == SIZE_MAX)
|
|
return;
|
|
context->images[index] = context->images[--context->image_count];
|
|
context->frame_valid = 0;
|
|
}
|
|
|
|
void
|
|
wr_context_clear_images(wr_context* context)
|
|
{
|
|
if (context) {
|
|
context->image_count = 0;
|
|
context->frame_valid = 0;
|
|
}
|
|
}
|
|
|
|
int
|
|
wr_context_begin_transaction(wr_context* context)
|
|
{
|
|
wr_scene_transaction transaction = { 0, NULL };
|
|
if (!context || !wr_reserve((void**)&context->transactions,
|
|
&context->transaction_capacity, context->transaction_depth + 1,
|
|
sizeof(*context->transactions)))
|
|
return 0;
|
|
transaction.command_count = context->command_count;
|
|
if (transaction.command_count) {
|
|
transaction.commands = malloc(transaction.command_count * sizeof(*transaction.commands));
|
|
if (!transaction.commands)
|
|
return 0;
|
|
memcpy(transaction.commands, context->commands,
|
|
transaction.command_count * sizeof(*transaction.commands));
|
|
}
|
|
context->transactions[context->transaction_depth++] = transaction;
|
|
return 1;
|
|
}
|
|
|
|
int
|
|
wr_context_commit_transaction(wr_context* context)
|
|
{
|
|
if (!context || !context->transaction_depth)
|
|
return 0;
|
|
free(context->transactions[--context->transaction_depth].commands);
|
|
context->frame_valid = 0;
|
|
return 1;
|
|
}
|
|
|
|
void
|
|
wr_context_abort_transaction(wr_context* context)
|
|
{
|
|
wr_scene_transaction transaction;
|
|
if (!context || !context->transaction_depth)
|
|
return;
|
|
transaction = context->transactions[--context->transaction_depth];
|
|
if (transaction.command_count)
|
|
memcpy(context->commands, transaction.commands,
|
|
transaction.command_count * sizeof(*context->commands));
|
|
context->command_count = transaction.command_count;
|
|
free(transaction.commands);
|
|
context->frame_valid = 0;
|
|
}
|
|
|
|
int
|
|
wr_context_remove_item(wr_context* context, wr_item_id item)
|
|
{
|
|
size_t index = wr_item_index(context, item);
|
|
if (index == SIZE_MAX)
|
|
return 0;
|
|
context->commands[index].active = 0;
|
|
context->frame_valid = 0;
|
|
return 1;
|
|
}
|
|
|
|
wr_item_id
|
|
wr_display_list_push_rect_with_id(wr_context* context, wr_item_id item,
|
|
wr_rect rect, wr_color color)
|
|
{
|
|
return wr_append(context, item, rect, color, WR_PRIMITIVE_SOLID, 0,
|
|
(wr_rect){ 0, 0, 1, 1 }) ? item : 0;
|
|
}
|
|
|
|
int
|
|
wr_display_list_update_rect(wr_context* context, wr_item_id item, wr_rect rect,
|
|
wr_color color, wr_transform transform)
|
|
{
|
|
size_t index = wr_item_index(context, item);
|
|
if (index == SIZE_MAX || !wr_valid_rect(rect) || !wr_valid_transform(transform))
|
|
return 0;
|
|
context->commands[index].rect = rect;
|
|
context->commands[index].color = wr_normalize_color(color);
|
|
context->commands[index].color.a *= context->opacity;
|
|
context->commands[index].transform = transform;
|
|
context->frame_valid = 0;
|
|
return 1;
|
|
}
|
|
|
|
int
|
|
wr_display_list_push_image(wr_context* context, wr_rect rect, uint32_t key,
|
|
wr_rect tex_rect, wr_color tint)
|
|
{ return wr_append(context, 0, rect, tint, WR_PRIMITIVE_IMAGE, key, tex_rect); }
|
|
|
|
wr_item_id
|
|
wr_display_list_push_image_with_id(wr_context* context, wr_item_id item,
|
|
wr_rect rect, uint32_t key, wr_rect tex,
|
|
wr_color tint)
|
|
{ return wr_append(context, item, rect, tint, WR_PRIMITIVE_IMAGE, key, tex) ? item : 0; }
|
|
|
|
int
|
|
wr_display_list_push_linear_gradient(wr_context* context, wr_rect rect,
|
|
wr_color start, wr_color end, int horizontal)
|
|
{
|
|
unsigned i;
|
|
for (i = 0; i < 32; ++i) {
|
|
float a = (float)i / 32.0f, b = (float)(i + 1) / 32.0f;
|
|
wr_rect slice = rect;
|
|
wr_color color = { start.r + (end.r-start.r)*(a+b)*.5f,
|
|
start.g + (end.g-start.g)*(a+b)*.5f, start.b + (end.b-start.b)*(a+b)*.5f,
|
|
start.a + (end.a-start.a)*(a+b)*.5f };
|
|
if (horizontal) { slice.x += rect.width*a; slice.width = rect.width*(b-a); }
|
|
else { slice.y += rect.height*a; slice.height = rect.height*(b-a); }
|
|
if (!wr_append(context, 0, slice, color, WR_PRIMITIVE_SOLID, 0,
|
|
(wr_rect){ 0, 0, 1, 1 })) return 0;
|
|
}
|
|
return 1;
|
|
}
|
|
|
|
int
|
|
wr_display_list_push_rounded_rect(wr_context* context, wr_rect rect,
|
|
wr_color color, float radius)
|
|
{
|
|
unsigned i;
|
|
(void)radius;
|
|
for (i = 0; i < 16; ++i) {
|
|
wr_rect slice = { rect.x, rect.y + rect.height * i / 16.0f,
|
|
rect.width, rect.height / 16.0f };
|
|
if (!wr_append(context, 0, slice, color, WR_PRIMITIVE_SOLID, 0,
|
|
(wr_rect){ 0, 0, 1, 1 }))
|
|
return 0;
|
|
}
|
|
return 1;
|
|
}
|
|
|
|
int
|
|
wr_display_list_push_glyph_run(wr_context* context, uint32_t key,
|
|
const wr_glyph* glyphs, size_t count, wr_color color)
|
|
{
|
|
size_t i;
|
|
for (i = 0; glyphs && i < count; ++i)
|
|
if (!wr_append(context, 0, glyphs[i].rect, color, WR_PRIMITIVE_IMAGE,
|
|
key, glyphs[i].tex_rect)) return 0;
|
|
return glyphs && count != 0;
|
|
}
|
|
|
|
int
|
|
wr_command_occluded(const wr_context* context, size_t index)
|
|
{
|
|
size_t i;
|
|
wr_rect bounds = wr_transform_bounds(context->commands[index].rect,
|
|
context->commands[index].transform);
|
|
for (i = index + 1; i < context->command_count; ++i) {
|
|
const wr_rect_command* covering = &context->commands[i];
|
|
wr_rect cover;
|
|
if (!covering->active || covering->kind != WR_PRIMITIVE_SOLID ||
|
|
covering->color.a != 1.0f) continue;
|
|
cover = wr_transform_bounds(covering->rect, covering->transform);
|
|
if (wr_rect_contains(cover, bounds)) return 1;
|
|
}
|
|
return 0;
|
|
}
|