first attempt for the layout class and property system

This commit is contained in:
Gwendolyn 2023-02-02 22:15:44 +01:00
commit 29b5bda326
21 changed files with 881 additions and 0 deletions

2
.gitignore vendored Normal file
View file

@ -0,0 +1,2 @@
/.idea
/cmake-*

35
CMakeLists.txt Normal file
View file

@ -0,0 +1,35 @@
cmake_minimum_required(VERSION 3.24)
project(clay C)
set(CMAKE_C_STANDARD 17)
# todo: use FetchContent instead https://cmake.org/cmake/help/latest/module/FetchContent.html#examples
find_package(PkgConfig)
pkg_check_modules(PC_CAIRO QUIET cairo)
find_path(CAIRO_INCLUDE_DIRS
NAMES cairo.h
HINTS ${PC_CAIRO_INCLUDEDIR}
${PC_CAIRO_INCLUDE_DIRS}
PATH_SUFFIXES cairo
)
find_library(CAIRO_LIBRARIES
NAMES cairo
HINTS ${PC_CAIRO_LIBDIR}
${PC_CAIRO_LIBRARY_DIRS}
)
add_library(clay src/clay.c src/clay-base.c src/clay-context.c src/clay-layout.c src/clay-property.c src/clay-text.c
src/clay-flex.c src/clay-document.c src/clay-color.c)
target_include_directories(clay PUBLIC include)
target_include_directories(clay PRIVATE ${CAIRO_INCLUDE_DIRS})
target_link_libraries(clay PRIVATE ${CAIRO_LIBRARIES})
target_compile_options(clay PRIVATE -Wall -Werror)
if(PROJECT_IS_TOP_LEVEL)
add_executable(clay-demo src/demo.c)
target_link_libraries(clay-demo PRIVATE clay)
endif()

18
include/clay-base.h Normal file
View file

@ -0,0 +1,18 @@
#ifndef CLAYOUT_CLAY_BASE_H
#define CLAYOUT_CLAY_BASE_H
typedef struct clay_ctx_t *clay_ctx;
typedef struct clay_t *clay;
clay_ctx clay_create_context(void);
void clay_destroy_context(clay_ctx);
void clay_set(clay, const char*, ...);
clay clay_clone(clay);
#endif //CLAYOUT_CLAY_BASE_H

40
include/clay-flex.h Normal file
View file

@ -0,0 +1,40 @@
#ifndef CLAYOUT_CLAY_FLEX_H
#define CLAYOUT_CLAY_FLEX_H
enum clay_flex_direction_e {
CLAY_FLEX_DIRECTION_ROW = 0,
CLAY_FLEX_DIRECTION_ROW_REVERSE = 1,
CLAY_FLEX_DIRECTION_COLUMN = 2,
CLAY_FLEX_DIRECTION_COLUMN_REVERSE = 3,
};
enum clay_flex_wrap_e {
CLAY_FLEX_WRAP_NO_WRAP = 0,
CLAY_FLEX_WRAP_WRAP = 1,
CLAY_FLEX_WRAP_WRAP_REVERSE = 2,
};
enum clay_flex_align_items_e {
CLAY_FLEX_ALIGN_ITEMS_START = 0,
CLAY_FLEX_ALIGN_ITEMS_END = 1,
CLAY_FLEX_ALIGN_ITEMS_CENTER = 2,
CLAY_FLEX_ALIGN_ITEMS_STRETCH = 3,
};
enum clay_flex_align_content_e {
CLAY_FLEX_ALIGN_CONTENT_START = 0,
CLAY_FLEX_ALIGN_CONTENT_END = 1,
CLAY_FLEX_ALIGN_CONTENT_CENTER = 2,
CLAY_FLEX_ALIGN_CONTENT_STRETCH = 3,
CLAY_FLEX_ALIGN_CONTENT_SPACE_BETWEEN = 4,
CLAY_FLEX_ALIGN_CONTENT_SPACE_AROUND = 5,
CLAY_FLEX_ALIGN_CONTENT_SPACE_EVENLY = 6,
};
clay clay_create_flex(clay_ctx);
void clay_flex_register_props(clay_ctx ctx); // todo: should be private
#endif //CLAYOUT_CLAY_FLEX_H

23
include/clay-properties.h Normal file
View file

@ -0,0 +1,23 @@
#ifndef CLAYOUT_CLAY_PROPERTIES_H
#define CLAYOUT_CLAY_PROPERTIES_H
#define CLAY_PROPERTY_TEXT 1
#define CLAY_PROPERTY_BG_COLOR 2
#define CLAY_PROPERTY_WIDTH 3
#define CLAY_PROPERTY_FLEX_GROW 4
#define CLAY_PROPERTY_FLEX_SHRINK 5
#define CLAY_PROPERTY_TEXT_ALIGN 6
#define CLAY_PROPERTY_TEXT_VERTICAL_ALIGN 7
#define CLAY_PROPERTY_FLEX_DIRECTION 8
#define CLAY_PROPERTY_FLEX_WRAP 9
#define CLAY_PROPERTY_FLEX_ALIGN_ITEMS 10
#define CLAY_PROPERTY_FLEX_ALIGN_CONTENT 11
#define CLAY_PROPERTY_FLEX_GAP 12
#define CLAY_PROPERTY_PADDING 13
#define CLAY_PROPERTY_CONTENTS 14
#define CLAY_PROPERTY_HEIGHT 15
#define CLAY_PROPERTY_CONTENT 16
#endif

20
include/clay-text.h Normal file
View file

@ -0,0 +1,20 @@
#ifndef CLAYOUT_CLAY_TEXT_H
#define CLAYOUT_CLAY_TEXT_H
enum clay_text_align_e {
CLAY_TEXT_ALIGN_LEFT = 0,
CLAY_TEXT_ALIGN_CENTER = 1,
CLAY_TEXT_ALIGN_RIGHT = 2,
};
enum clay_text_vertical_align_e {
CLAY_TEXT_VERTICAL_ALIGN_TOP = 0,
CLAY_TEXT_VERTICAL_ALIGN_MIDDLE = 1,
CLAY_TEXT_VERTICAL_ALIGN_BOTTOM = 2,
};
clay clay_create_text(clay_ctx);
void clay_text_register_props(clay_ctx ctx); // todo: should be private
#endif //CLAYOUT_CLAY_TEXT_H

20
include/clay.h Normal file
View file

@ -0,0 +1,20 @@
#ifndef CLAYOUT_CLAY_H
#define CLAYOUT_CLAY_H
#include "clay-base.h"
#include "clay-properties.h"
#include "clay-flex.h"
#include "clay-text.h"
clay clay_create_document(clay_ctx);
void clay_render_to_png(clay, const char *);
void clay_debug_layout(clay doc);
void clay_document_register_props(clay_ctx ctx); // todo: should be private
#endif //CLAYOUT_CLAY_H

7
src/clay-base.c Normal file
View file

@ -0,0 +1,7 @@
#include <malloc.h>
#include <string.h>
#include "clay-base.h"
#include <assert.h>

10
src/clay-color.c Normal file
View file

@ -0,0 +1,10 @@
//
// Created by gwendolyn on 2/2/23.
//
#include "clay-color.h"
clay_color clay_color_rgba(uint8_t r, uint8_t g, uint8_t b, uint8_t a) {
clay_color color = {.r = r, .g = g, .b = b, .a = a};
return color;
}

15
src/clay-color.h Normal file
View file

@ -0,0 +1,15 @@
#ifndef CLAY_CLAY_COLOR_H
#define CLAY_CLAY_COLOR_H
#include <stdint.h>
typedef struct {
uint8_t r;
uint8_t g;
uint8_t b;
uint8_t a;
} clay_color;
clay_color clay_color_rgba(uint8_t r, uint8_t g, uint8_t b, uint8_t a);
#endif //CLAY_CLAY_COLOR_H

125
src/clay-context.c Normal file
View file

@ -0,0 +1,125 @@
#include <clay.h>
#include <stddef.h>
#include <malloc.h>
#include <assert.h>
#include <stdbool.h>
#include <string.h>
#include "clay-layout.h"
#include "clay-context.h"
// todo: thread safety? maybe as an option CLAY_ENABLE_THREADSAFE
struct clay_ctx_t {
clay *layouts_ptrs;
size_t layouts_length;
size_t layouts_size;
clay_property_desc_s *property_descs;
size_t property_descs_length;
size_t property_descs_size;
int property_tag_cnt;
};
clay_ctx clay_create_context(void) {
clay_ctx ctx = malloc(sizeof *ctx);
assert(ctx != NULL);
ctx->layouts_size = 16;
ctx->layouts_length = 0;
ctx->layouts_ptrs = malloc(sizeof(*ctx->layouts_ptrs) * ctx->layouts_size);
assert(ctx->layouts_ptrs != NULL);
ctx->property_tag_cnt = 0;
ctx->property_descs_size = 16;
ctx->property_descs_length = 0;
ctx->property_descs = malloc(sizeof(*ctx->property_descs) * ctx->property_descs_size);
assert(ctx->property_descs != NULL);
clay_text_register_props(ctx);
clay_flex_register_props(ctx);
clay_document_register_props(ctx);
return ctx;
}
void clay_destroy_context(clay_ctx ctx) {
// TODO: free everything owned by ctx
for (size_t i = 0; i < ctx->layouts_length; ++i) {
clay layout = ctx->layouts_ptrs[i];
clay_cleanup_layout(layout);
free(layout);
}
free(ctx->layouts_ptrs);
free(ctx->property_descs);
free(ctx);
}
void clay_ctx_register_layout(clay_ctx ctx, clay layout) {
assert(ctx->layouts_length <= ctx->layouts_size);
if (ctx->layouts_length == ctx->layouts_size) {
size_t new_size = ctx->layouts_size * 2;
ctx->layouts_ptrs = realloc(ctx->layouts_ptrs, sizeof(*ctx->layouts_ptrs) * new_size);
assert(ctx->layouts_ptrs != NULL);
ctx->layouts_size = new_size;
}
ctx->layouts_length += 1;
ctx->layouts_ptrs[ctx->layouts_length - 1] = layout;
}
void clay_ctx_unregister_layout(clay_ctx ctx, clay layout) {
for (size_t i = 0; i < ctx->layouts_length; ++i) {
if (ctx->layouts_ptrs[i] == layout) {
ctx->layouts_ptrs[i] = ctx->layouts_ptrs[ctx->layouts_length - 1];
ctx->layouts_length -= 1;
}
}
}
int clay_ctx_register_property(clay_ctx ctx, const char *name, clay_property_type type) {
assert (!clay_ctx_has_property(ctx, name));
int tag = ++ctx->property_tag_cnt;
assert(ctx->property_descs_length <= ctx->property_descs_size);
if (ctx->property_descs_length == ctx->property_descs_size) {
size_t new_size = ctx->property_descs_size * 2;
ctx->property_descs = realloc(ctx->property_descs, sizeof(*ctx->property_descs) * new_size);
assert(ctx->property_descs != NULL);
ctx->property_descs_size = new_size;
}
ctx->property_descs_length += 1;
ctx->property_descs[ctx->property_descs_length - 1] = (clay_property_desc_s) {
.type = type,
.tag = tag,
.name = name
};
return tag;
}
void clay_ctx_unregister_property(clay_ctx ctx, int tag) {
for (size_t i = 0; i < ctx->property_descs_length; ++i) {
if (ctx->property_descs[i].tag == tag) {
ctx->property_descs[i] = ctx->property_descs[ctx->property_descs_length - 1];
ctx->property_descs_length -= 1;
return;
}
}
}
bool clay_ctx_has_property(clay_ctx ctx, const char *name) {
for (size_t i = 0; i < ctx->property_descs_length; ++i) {
if (strcmp(ctx->property_descs[i].name, name) == 0) {
return true;
}
}
return false;
}
clay_property_desc clay_ctx_get_property_desc(clay_ctx ctx, const char *name) {
for (size_t i = 0; i < ctx->property_descs_length; ++i) {
if (strcmp(ctx->property_descs[i].name, name) == 0) {
return &ctx->property_descs[i];
}
}
return NULL;
}

23
src/clay-context.h Normal file
View file

@ -0,0 +1,23 @@
#ifndef CLAY_CLAY_CONTEXT_H
#define CLAY_CLAY_CONTEXT_H
#include "clay-property.h"
#include <stdbool.h>
typedef struct {
const char * name;
int tag;
clay_property_type type;
} clay_property_desc_s, *clay_property_desc;
// TODO: properties should not keep track of the type and allow any type, or something?
void clay_ctx_register_layout(clay_ctx ctx, clay layout);
void clay_ctx_unregister_layout(clay_ctx ctx, clay layout);
int clay_ctx_register_property(clay_ctx ctx, const char * name, clay_property_type type);
void clay_ctx_unregister_property(clay_ctx ctx, int tag);
bool clay_ctx_has_property(clay_ctx ctx, const char *name);
clay_property_desc clay_ctx_get_property_desc(clay_ctx ctx, const char * name);
#endif //CLAY_CLAY_CONTEXT_H

70
src/clay-document.c Normal file
View file

@ -0,0 +1,70 @@
#include "clay.h"
#include "clay-layout.h"
#include "clay-context.h"
#include "clay-color.h"
static void cleanup_document(clay layout);
static void init_document(clay layout);
static void debug_document(clay layout);
static struct layout_class layout_class_document = {
.init = &init_document,
.cleanup = &cleanup_document,
.debug = &debug_document,
};
static void init_document(clay layout) {
// todo: anything?
}
static void cleanup_document(clay layout) {
// todo: anything?
}
static void debug_document(clay layout) {
printf("document:\n");
clay_property_value width_prop = clay_get_prop(layout, "width");
clay_property_value height_prop = clay_get_prop(layout, "height");
clay_property_value content_prop = clay_get_prop(layout, "content");
clay_property_value bgcolor_prop = clay_get_prop(layout, "bg-color");
if (width_prop->type == CLAY_PROPERTY_INT) {
printf(" width: %d\n", width_prop->int_val);
}
if (height_prop->type == CLAY_PROPERTY_INT) {
printf(" height: %d\n", height_prop->int_val);
}
if (bgcolor_prop->type == CLAY_PROPERTY_POINTER) {
clay_color *color = (clay_color*)bgcolor_prop->pointer_val;
printf(" bg-color: (%d, %d, %d, %d)\n", color->r, color->g, color->b, color->a);
}
printf("\n");
if (content_prop->type == CLAY_PROPERTY_POINTER && content_prop->pointer_val != NULL) {
clay content = (clay) content_prop->pointer_val;
content->class.debug(content);
}
}
clay clay_create_document(clay_ctx ctx) {
return clay_create_layout(ctx, layout_class_document);
}
void clay_render_to_png(clay doc, const char *path) {
// todo
}
void clay_debug_layout(clay doc) {
doc->class.debug(doc);
}
void clay_document_register_props(clay_ctx ctx) {
clay_ctx_register_property(ctx, "width", CLAY_PROPERTY_INT);
clay_ctx_register_property(ctx, "height", CLAY_PROPERTY_INT);
clay_ctx_register_property(ctx, "content", CLAY_PROPERTY_POINTER);
clay_ctx_register_property(ctx, "bg-color", CLAY_PROPERTY_POINTER);
}

82
src/clay-flex.c Normal file
View file

@ -0,0 +1,82 @@
#include "clay.h"
#include "clay-layout.h"
#include "clay-context.h"
static void cleanup_flex(clay layout);
static void init_flex(clay layout);
static void debug_flex(clay layout);
static struct layout_class layout_class_flex = {
.init = &init_flex,
.cleanup = &cleanup_flex,
.debug = &debug_flex,
};
static void init_flex(clay layout) {
// todo: anything?
}
static void cleanup_flex(clay layout) {
// todo: anything?
}
static void debug_flex(clay layout) {
printf("flex:\n");
clay_property_value direction_prop = clay_get_prop(layout, "direction");
clay_property_value wrap_prop = clay_get_prop(layout, "wrap");
clay_property_value align_items_prop = clay_get_prop(layout, "align-items");
clay_property_value align_content_prop = clay_get_prop(layout, "align-content");
clay_property_value gap_prop = clay_get_prop(layout, "gap");
clay_property_value padding_prop = clay_get_prop(layout, "padding");
clay_property_value contents_prop = clay_get_prop(layout, "contents");
if (direction_prop->type == CLAY_PROPERTY_POINTER) {
printf(" direction: %s\n", (char*)direction_prop->pointer_val);
}
if (wrap_prop->type == CLAY_PROPERTY_POINTER) {
printf(" wrap: %s\n", (char*)wrap_prop->pointer_val);
}
if (align_items_prop->type == CLAY_PROPERTY_POINTER) {
printf(" align-items: %s\n", (char*)align_items_prop->pointer_val);
}
if (align_content_prop->type == CLAY_PROPERTY_POINTER) {
printf(" align-content: %s\n", (char*)align_content_prop->pointer_val);
}
if (gap_prop->type == CLAY_PROPERTY_INT) {
printf(" gap: %d\n", gap_prop->int_val);
}
if (padding_prop->type == CLAY_PROPERTY_INT) {
printf(" padding: %d\n", padding_prop->int_val);
}
printf("\n");
if (contents_prop->type == CLAY_PROPERTY_POINTER) {
clay* ptr = (clay*)contents_prop->pointer_val;
while(*ptr != NULL) {
clay content = *ptr;
content->class.debug(content);
ptr += 1;
}
}
}
clay clay_create_flex(clay_ctx ctx) {
return clay_create_layout(ctx, layout_class_flex);
}
void clay_flex_register_props(clay_ctx ctx) {
clay_ctx_register_property(ctx, "direction", CLAY_PROPERTY_POINTER);
clay_ctx_register_property(ctx, "wrap", CLAY_PROPERTY_POINTER);
clay_ctx_register_property(ctx, "align-items", CLAY_PROPERTY_POINTER);
clay_ctx_register_property(ctx, "align-content", CLAY_PROPERTY_POINTER);
clay_ctx_register_property(ctx, "gap", CLAY_PROPERTY_INT);
clay_ctx_register_property(ctx, "padding", CLAY_PROPERTY_INT);
clay_ctx_register_property(ctx, "contents", CLAY_PROPERTY_POINTER);
clay_ctx_register_property(ctx, "flex:grow", CLAY_PROPERTY_POINTER);
clay_ctx_register_property(ctx, "flex:shrink", CLAY_PROPERTY_POINTER);
}

78
src/clay-layout.c Normal file
View file

@ -0,0 +1,78 @@
#include <malloc.h>
#include <stdarg.h>
#include <assert.h>
#include "clay-layout.h"
#include "clay-context.h"
#include "clay-property.h"
clay clay_create_layout(clay_ctx ctx, struct layout_class class) {
clay layout = malloc(sizeof(*layout));
assert(layout != NULL);
layout->properties = clay_propset_create();
layout->class = class;
layout->ctx = ctx;
if (layout->class.init != NULL) {
layout->class.init(layout);
}
clay_ctx_register_layout(ctx, layout);
return layout;
}
void clay_destroy_layout(clay layout) {
clay_ctx_unregister_layout(layout->ctx, layout);
clay_cleanup_layout(layout);
free(layout);
}
void clay_cleanup_layout(clay layout) {
if (layout->class.cleanup != NULL) {
layout->class.cleanup(layout);
}
clay_propset_destroy(layout->properties);
}
clay clay_clone(clay layout) {
clay cloned = malloc(sizeof(*cloned));
cloned->class = layout->class;
cloned->ctx = layout->ctx;
cloned->properties = clay_propset_clone(layout->properties);
return cloned;
}
clay_property_value clay_get_prop(clay layout, const char *prop) {
clay_ctx ctx = layout->ctx;
clay_property_desc desc = clay_ctx_get_property_desc(ctx, prop);
assert(desc != NULL);
assert(desc->type != CLAY_PROPERTY_NOT_SET);
return clay_property_get_by_tag(layout->properties, desc->tag);
}
void clay_set(clay layout, const char *prop, ...) {
// TODO: use a macro so that a property can have values of different types
// the property registry should not keep the type then
// also the property registry can have some kind of alias mechanism for translating strings to enums or something
clay_ctx ctx = layout->ctx;
clay_property_desc desc = clay_ctx_get_property_desc(ctx, prop);
assert(desc != NULL);
assert(desc->type != CLAY_PROPERTY_NOT_SET);
struct clay_property_value value;
value.type = desc->type;
va_list args;
va_start(args, prop);
switch (desc->type) {
case CLAY_PROPERTY_NOT_SET:
break;
case CLAY_PROPERTY_INT:
value.int_val = va_arg(args, int);
break;
case CLAY_PROPERTY_FLOAT:
value.float_val = va_arg(args, double);
break;
case CLAY_PROPERTY_POINTER:
value.pointer_val = va_arg(args, void*);
break;
}
va_end(args);
clay_property_set_by_tag(layout->properties, desc->tag, value);
}

33
src/clay-layout.h Normal file
View file

@ -0,0 +1,33 @@
#ifndef CLAY_CLAY_LAYOUT_H
#define CLAY_CLAY_LAYOUT_H
#include "clay.h"
#include "clay-property.h"
typedef void (*init_fn)(clay);
typedef void (*cleanup_fn)(clay);
typedef void (*debug_fn)(clay);
struct layout_class {
init_fn init;
cleanup_fn cleanup;
debug_fn debug;
};
struct clay_t {
struct layout_class class;
clay_property_set properties;
clay_ctx ctx;
};
clay clay_create_layout(clay_ctx ctx, struct layout_class class);
void clay_destroy_layout(clay layout);
void clay_cleanup_layout(clay layout);
clay_property_value clay_get_prop(clay layout, const char *prop);
#endif //CLAY_CLAY_LAYOUT_H

87
src/clay-property.c Normal file
View file

@ -0,0 +1,87 @@
#include <string.h>
#include "clay-property.h"
struct clay_property {
int tag;
struct clay_property_value value;
};
struct clay_property_set_t {
struct clay_property *props;
size_t length;
size_t size;
};
static struct clay_property_value empty_property_value = {
.type = CLAY_PROPERTY_NOT_SET,
};
clay_property_set clay_propset_create(void) {
clay_property_set propset = malloc(sizeof(*propset));
assert(propset != NULL);
propset->length = 0;
propset->size = 16;
propset->props = malloc(sizeof(*propset->props) * 16);
assert(propset->props != NULL);
return propset;
}
clay_property_set clay_propset_clone(clay_property_set propset) {
clay_property_set cloned = malloc(sizeof(*cloned));
assert(propset != NULL);
cloned->length = propset->length;
cloned->size = propset->size;
cloned->props = malloc(sizeof(*cloned->props) * cloned->size);
memcpy(cloned->props, propset->props, sizeof(*cloned->props) * cloned->size);
return cloned;
}
void clay_propset_destroy(clay_property_set propset) {
free(propset->props);
free(propset);
}
clay_property_value clay_property_get_by_tag(clay_property_set propset, int tag) {
for (size_t i = 0; i < propset->length; ++i) {
struct clay_property *prop = &propset->props[i];
if (prop->tag == tag) {
return &prop->value;
}
}
return &empty_property_value;
}
void clay_property_set_by_tag(clay_property_set propset, int tag, struct clay_property_value value) {
struct clay_property *prop = NULL;
for (size_t i = 0; i < propset->length; ++i) {
if (propset->props[i].tag == tag) {
prop = &propset->props[i];
break;
}
}
if (prop == NULL) {
assert(propset->length <= propset->size);
if (propset->length == propset->size) {
size_t new_size = propset->size * 2;
propset->props = realloc(propset->props, sizeof(*propset->props) * new_size);
assert(propset->props != NULL);
propset->size = new_size;
}
propset->length += 1;
prop = &propset->props[propset->length - 1];
}
prop->tag = tag;
prop->value = value;
}
void clay_property_delete_by_tag(clay_property_set propset, int tag) {
for (size_t i = 0; i < propset->length; ++i) {
struct clay_property *prop = &propset->props[i];
if (prop->tag == tag) {
prop->value = empty_property_value;
}
}
}

41
src/clay-property.h Normal file
View file

@ -0,0 +1,41 @@
#ifndef CLAY_CLAY_PROPERTY_H
#define CLAY_CLAY_PROPERTY_H
#include <stddef.h>
#include <assert.h>
#include <malloc.h>
typedef enum {
CLAY_PROPERTY_NOT_SET,
CLAY_PROPERTY_INT,
CLAY_PROPERTY_FLOAT,
CLAY_PROPERTY_POINTER,
} clay_property_type;
struct clay_property_value {
clay_property_type type;
union {
int int_val;
double float_val;
void *pointer_val;
};
};
typedef const struct clay_property_value *clay_property_value;
typedef struct clay_property_set_t *clay_property_set;
clay_property_set clay_propset_create(void);
clay_property_set clay_propset_clone(clay_property_set);
void clay_propset_destroy(clay_property_set propset);
clay_property_value clay_property_get_by_tag(clay_property_set propset, int tag);
void clay_property_set_by_tag(clay_property_set propset, int tag, struct clay_property_value value);
void clay_property_delete_by_tag(clay_property_set propset, int tag);
#endif //CLAY_CLAY_PROPERTY_H

67
src/clay-text.c Normal file
View file

@ -0,0 +1,67 @@
#include "clay.h"
#include "clay-layout.h"
#include "clay-context.h"
#include "clay-color.h"
static void cleanup_text(clay layout);
static void init_text(clay layout);
static void debug_text(clay layout);
static struct layout_class layout_class_text = {
.cleanup = &cleanup_text,
.init = &init_text,
.debug = &debug_text,
};
static void init_text(clay layout) {
// todo: anything?
}
static void cleanup_text(clay layout) {
// todo: anything?
}
static void debug_text(clay layout) {
printf("text:\n");
clay_property_value content_prop = clay_get_prop(layout, "content");
clay_property_value bgcolor_prop = clay_get_prop(layout, "bg-color");
clay_property_value width_prop = clay_get_prop(layout, "width");
clay_property_value flex_grow_prop = clay_get_prop(layout, "flex:grow");
clay_property_value flex_shrink_prop = clay_get_prop(layout, "flex:shrink");
clay_property_value align_prop = clay_get_prop(layout, "align");
clay_property_value vertical_align_prop = clay_get_prop(layout, "vertical-align");
if (content_prop->type == CLAY_PROPERTY_POINTER) {
printf(" content: %s\n", (char*)content_prop->pointer_val);
}
if (bgcolor_prop->type == CLAY_PROPERTY_POINTER) {
clay_color *color = (clay_color*)bgcolor_prop->pointer_val;
printf(" bg-color: (%d, %d, %d, %d)\n", color->r, color->g, color->b, color->a);
}
if (width_prop->type == CLAY_PROPERTY_INT) {
printf(" width: %d\n", width_prop->int_val);
}
if (flex_grow_prop->type == CLAY_PROPERTY_INT) {
printf(" flex-grow: %d\n", flex_grow_prop->int_val);
}
if (flex_shrink_prop->type == CLAY_PROPERTY_INT) {
printf(" flex-shrink: %d\n", flex_shrink_prop->int_val);
}
if (align_prop->type == CLAY_PROPERTY_POINTER) {
printf(" align: %s\n", (char*)align_prop->pointer_val);
}
if (vertical_align_prop->type == CLAY_PROPERTY_POINTER) {
printf(" vertical-align: %s\n", (char*)vertical_align_prop->pointer_val);
}
}
clay clay_create_text(clay_ctx ctx) {
return clay_create_layout(ctx, layout_class_text);
}
void clay_text_register_props(clay_ctx ctx) {
clay_ctx_register_property(ctx, "align", CLAY_PROPERTY_POINTER);
clay_ctx_register_property(ctx, "vertical-align", CLAY_PROPERTY_POINTER);
}

20
src/clay.c Normal file
View file

@ -0,0 +1,20 @@
#include "clay.h"
#include <cairo/cairo.h>
#include <stdio.h>
void hello(void) {
cairo_surface_t *surface = cairo_image_surface_create (CAIRO_FORMAT_ARGB32, 240, 80);
cairo_t *cr = cairo_create (surface);
cairo_select_font_face (cr, "sans-serif", CAIRO_FONT_SLANT_ITALIC, CAIRO_FONT_WEIGHT_BOLD);
cairo_set_font_size (cr, 10.0);
cairo_set_source_rgb (cr, 0.0, 0.0, 1.0);
cairo_move_to (cr, 10.0, 50.0);
cairo_show_text (cr, "Hello, world");
cairo_destroy (cr);
cairo_surface_write_to_png (surface, "hello.png");
cairo_surface_destroy (surface);
}

65
src/demo.c Normal file
View file

@ -0,0 +1,65 @@
#include <stddef.h>
#include "clay.h"
#include "clay-color.h"
int main(int argc, char **argv) {
clay_ctx ctx = clay_create_context();
clay_color c1 = clay_color_rgba(4, 231, 98, 128);
clay_color c2 = clay_color_rgba(34, 49, 39, 128);
clay_color c3 = clay_color_rgba(220, 0, 115, 128);
clay_color c4 = clay_color_rgba(0, 139, 248, 128);
clay_color c5 = clay_color_rgba(71, 0, 99, 128);
clay_color cbg = clay_color_rgba(206, 249, 242, 255);
clay t1 = clay_create_text(ctx);
clay_set(t1, "content", "ITEM 1");
clay_set(t1, "bg-color", &c1);
clay_set(t1, "width", 100);
clay_set(t1, "flex:grow", 1);
clay_set(t1, "flex:shrink", 1);
clay_set(t1, "align", "center");
clay_set(t1, "vertical-align", "middle");
clay t2 = clay_clone(t1);
clay_set(t2, "content", "ITEM 2");
clay_set(t2, "bg-color", &c2);
clay_set(t2, "width", 300);
clay t3 = clay_clone(t1);
clay_set(t3, "content", "ITEM 3");
clay_set(t3, "bg-color", &c3);
clay_set(t3, "width", 200);
clay t4 = clay_clone(t1);
clay_set(t4, "content", "ITEM 4");
clay_set(t4, "bg-color", &c4);
clay_set(t4, "width", 400);
clay t5 = clay_clone(t1);
clay_set(t5, "content", "ITEM 5");
clay_set(t5, "bg-color", &c5);
clay_set(t5, "width", 250);
clay flex = clay_create_flex(ctx);
clay_set(flex, "direction", "row");
clay_set(flex, "wrap", "wrap");
clay_set(flex, "align-items", "stretch");
clay_set(flex, "align-content", "stretch");
clay_set(flex, "gap", 20);
clay_set(flex, "padding", 20);
clay_set(flex, "contents", (clay[]) {t1, t2, t3, t4, t5, NULL});
clay doc = clay_create_document(ctx);
clay_set(doc, "width", 800);
clay_set(doc, "height", 400);
clay_set(doc, "bg-color", &cbg);
clay_set(doc, "content", flex);
clay_debug_layout(doc);
clay_destroy_context(ctx);
}