mirror of
https://github.com/nicbarker/clay.git
synced 2025-01-23 01:46:02 +00:00
Compare commits
11 Commits
dfc87f4f15
...
eea578ecea
Author | SHA1 | Date | |
---|---|---|---|
|
eea578ecea | ||
|
9d659e8abd | ||
|
ec2b3b35ff | ||
|
5f7176cdcc | ||
|
ebeef93c34 | ||
|
9b2d585499 | ||
|
81589ad29b | ||
|
16f894bb4d | ||
|
9f07f5aac8 | ||
|
63a74a92a8 | ||
|
8d3cadc52e |
67
README.md
67
README.md
@ -28,17 +28,31 @@ _An example GUI application built with clay_
|
|||||||
#include "clay.h"
|
#include "clay.h"
|
||||||
```
|
```
|
||||||
|
|
||||||
2. Ask clay for how much static memory it needs using [Clay_MinMemorySize()](#clay_minmemorysize), create an Arena for it to use with [Clay_CreateArenaWithCapacityAndMemory(size, void *memory)](#clay_createarenawithcapacityandmemory), and initialize it with [Clay_Initialize(arena, dimensions)](#clay_initialize).
|
2. Ask clay for how much static memory it needs using [Clay_MinMemorySize()](#clay_minmemorysize), create an Arena for it to use with [Clay_CreateArenaWithCapacityAndMemory(size, void *memory)](#clay_createarenawithcapacityandmemory).
|
||||||
|
|
||||||
```C
|
```C
|
||||||
// Note: malloc is only used here as an example, any allocator that provides
|
// Note: malloc is only used here as an example, any allocator that provides
|
||||||
// a pointer to addressable memory of at least totalMemorySize will work
|
// a pointer to addressable memory of at least totalMemorySize will work
|
||||||
uint64_t totalMemorySize = Clay_MinMemorySize();
|
uint64_t totalMemorySize = Clay_MinMemorySize();
|
||||||
Clay_Arena arena = Clay_CreateArenaWithCapacityAndMemory(totalMemorySize, malloc(totalMemorySize));
|
Clay_Arena arena = Clay_CreateArenaWithCapacityAndMemory(totalMemorySize, malloc(totalMemorySize));
|
||||||
Clay_Initialize(arena, (Clay_Dimensions) { screenWidth, screenHeight });
|
|
||||||
```
|
```
|
||||||
|
|
||||||
3. Provide a `MeasureText(text, config)` function pointer with [Clay_SetMeasureTextFunction(function)](#clay_setmeasuretextfunction) so that clay can measure and wrap text.
|
3. Create an [ErrorHandler](#clay_errorhandler) for Clay to call when an internal error occurs, and initialize Clay with the Arena and handler by calling [Clay_Initialize(arena, dimensions, errorHandler)](#clay_initialize).
|
||||||
|
|
||||||
|
```C
|
||||||
|
void HandleClayErrors(Clay_ErrorData errorData) {
|
||||||
|
// See the Clay_ErrorData struct for more information
|
||||||
|
printf("%s", errorData.errorText.chars);
|
||||||
|
switch(errorData.errorType) {
|
||||||
|
// etc
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// In your startup function
|
||||||
|
Clay_Initialize(arena, (Clay_Dimensions) { screenWidth, screenHeight }, (Clay_ErrorHandler) { HandleClayErrors });
|
||||||
|
```
|
||||||
|
|
||||||
|
4. Provide a `MeasureText(text, config)` function pointer with [Clay_SetMeasureTextFunction(function)](#clay_setmeasuretextfunction) so that clay can measure and wrap text.
|
||||||
|
|
||||||
```C
|
```C
|
||||||
// Example measure text function
|
// Example measure text function
|
||||||
@ -811,6 +825,53 @@ An offset version of [CLAY_ID](#clay_id). Generates a [Clay_ElementId](#clay_ele
|
|||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
### CLAY_ID_LOCAL()
|
||||||
|
|
||||||
|
**Usage**
|
||||||
|
|
||||||
|
`CLAY(CLAY_ID_LOCAL(char* idString)) {}`
|
||||||
|
|
||||||
|
**Lifecycle**
|
||||||
|
|
||||||
|
`Clay_BeginLayout()` -> `CLAY(` -> `CLAY_ID_LOCAL()` -> `)` -> `Clay_EndLayout()`
|
||||||
|
|
||||||
|
**Notes**
|
||||||
|
|
||||||
|
**CLAY_ID_LOCAL()** is used to generate and attach a [Clay_ElementId](#clay_elementid) to a layout element during declaration.
|
||||||
|
|
||||||
|
Unlike [CLAY_ID](#clay_id) which needs to be globally unique, a local ID is based on the ID of it's parent and only needs to be unique among its siblings.
|
||||||
|
|
||||||
|
As a result, local id is suitable for use in reusable components and loops.
|
||||||
|
|
||||||
|
**Examples**
|
||||||
|
|
||||||
|
```C
|
||||||
|
void RenderHeaderButton(ButtonData button) {
|
||||||
|
CLAY(
|
||||||
|
CLAY_ID_LOCAL("HeaderButton"),
|
||||||
|
CLAY_LAYOUT({ .layoutDirection = CLAY_TOP_TO_BOTTOM, .sizing = { .width = CLAY_SIZING_GROW(0) }, .padding = CLAY_PADDING_ALL(16), .childGap = 16) })
|
||||||
|
) {
|
||||||
|
// ...children
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i = 0; i < headerButtons.length; i++) {
|
||||||
|
RenderHeaderButton(headerButtons.items[i]);
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### CLAY_IDI_LOCAL()
|
||||||
|
|
||||||
|
`Clay_ElementId CLAY_IDI_LOCAL(char *label, int index)`
|
||||||
|
|
||||||
|
An offset version of [CLAY_ID_LOCAL](#clay_local_id). Generates a [Clay_ElementId](#clay_elementid) string id from the provided `char *label`, combined with the `int index`. Used for generating ids for sequential elements (such as in a `for` loop) without having to construct dynamic strings at runtime.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
### CLAY_LAYOUT
|
### CLAY_LAYOUT
|
||||||
|
|
||||||
**Usage**
|
**Usage**
|
||||||
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
9
clay.h
9
clay.h
@ -2257,12 +2257,6 @@ void Clay__SizeContainersAlongAxis(bool xAxis) {
|
|||||||
*childSize = (parentSize - totalPaddingAndChildGaps) * childSizing.size.percent;
|
*childSize = (parentSize - totalPaddingAndChildGaps) * childSizing.size.percent;
|
||||||
if (sizingAlongAxis) {
|
if (sizingAlongAxis) {
|
||||||
innerContentSize += *childSize;
|
innerContentSize += *childSize;
|
||||||
if (childOffset > 0) {
|
|
||||||
innerContentSize += parentChildGap; // For children after index 0, the childAxisOffset is the gap from the previous child
|
|
||||||
totalPaddingAndChildGaps += parentChildGap;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
innerContentSize = CLAY__MAX(*childSize, innerContentSize);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -2483,9 +2477,6 @@ void Clay__CalculateFinalLayout() {
|
|||||||
|
|
||||||
// DFS node has been visited, this is on the way back up to the root
|
// DFS node has been visited, this is on the way back up to the root
|
||||||
Clay_LayoutConfig *layoutConfig = currentElement->layoutConfig;
|
Clay_LayoutConfig *layoutConfig = currentElement->layoutConfig;
|
||||||
if (layoutConfig->sizing.height.type == CLAY__SIZING_TYPE_PERCENT) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if (layoutConfig->layoutDirection == CLAY_LEFT_TO_RIGHT) {
|
if (layoutConfig->layoutDirection == CLAY_LEFT_TO_RIGHT) {
|
||||||
// Resize any parent containers that have grown in height along their non layout axis
|
// Resize any parent containers that have grown in height along their non layout axis
|
||||||
for (int32_t j = 0; j < currentElement->childrenOrTextContent.children.length; ++j) {
|
for (int32_t j = 0; j < currentElement->childrenOrTextContent.children.length; ++j) {
|
||||||
|
Binary file not shown.
@ -117,7 +117,7 @@ int main(void) {
|
|||||||
|
|
||||||
Clay_RectangleElementConfig contentBackgroundConfig = {
|
Clay_RectangleElementConfig contentBackgroundConfig = {
|
||||||
.color = { 90, 90, 90, 255 },
|
.color = { 90, 90, 90, 255 },
|
||||||
.cornerRadius = 8
|
.cornerRadius = CLAY_CORNER_RADIUS(8)
|
||||||
};
|
};
|
||||||
|
|
||||||
Clay_BeginLayout();
|
Clay_BeginLayout();
|
||||||
@ -141,7 +141,7 @@ int main(void) {
|
|||||||
.height = CLAY_SIZING_FIXED(60),
|
.height = CLAY_SIZING_FIXED(60),
|
||||||
.width = CLAY_SIZING_GROW(0)
|
.width = CLAY_SIZING_GROW(0)
|
||||||
},
|
},
|
||||||
.padding = { 16 },
|
.padding = { 16, 16, 0, 0 },
|
||||||
.childGap = 16,
|
.childGap = 16,
|
||||||
.childAlignment = {
|
.childAlignment = {
|
||||||
.y = CLAY_ALIGN_Y_CENTER
|
.y = CLAY_ALIGN_Y_CENTER
|
||||||
@ -151,10 +151,10 @@ int main(void) {
|
|||||||
// Header buttons go here
|
// Header buttons go here
|
||||||
CLAY(
|
CLAY(
|
||||||
CLAY_ID("FileButton"),
|
CLAY_ID("FileButton"),
|
||||||
CLAY_LAYOUT({ .padding = { 16, 8 }}),
|
CLAY_LAYOUT({ .padding = { 16, 16, 8, 8 }}),
|
||||||
CLAY_RECTANGLE({
|
CLAY_RECTANGLE({
|
||||||
.color = { 140, 140, 140, 255 },
|
.color = { 140, 140, 140, 255 },
|
||||||
.cornerRadius = 5
|
.cornerRadius = CLAY_CORNER_RADIUS(5)
|
||||||
})
|
})
|
||||||
) {
|
) {
|
||||||
CLAY_TEXT(CLAY_STRING("File"), CLAY_TEXT_CONFIG({
|
CLAY_TEXT(CLAY_STRING("File"), CLAY_TEXT_CONFIG({
|
||||||
@ -177,7 +177,7 @@ int main(void) {
|
|||||||
},
|
},
|
||||||
}),
|
}),
|
||||||
CLAY_LAYOUT({
|
CLAY_LAYOUT({
|
||||||
.padding = {0, 8 }
|
.padding = {0, 0, 8, 8 }
|
||||||
})
|
})
|
||||||
) {
|
) {
|
||||||
CLAY(
|
CLAY(
|
||||||
@ -189,7 +189,7 @@ int main(void) {
|
|||||||
}),
|
}),
|
||||||
CLAY_RECTANGLE({
|
CLAY_RECTANGLE({
|
||||||
.color = { 40, 40, 40, 255 },
|
.color = { 40, 40, 40, 255 },
|
||||||
.cornerRadius = 8
|
.cornerRadius = CLAY_CORNER_RADIUS(8)
|
||||||
})
|
})
|
||||||
) {
|
) {
|
||||||
// Render dropdown items here
|
// Render dropdown items here
|
||||||
@ -236,7 +236,7 @@ int main(void) {
|
|||||||
CLAY_LAYOUT(sidebarButtonLayout),
|
CLAY_LAYOUT(sidebarButtonLayout),
|
||||||
CLAY_RECTANGLE({
|
CLAY_RECTANGLE({
|
||||||
.color = { 120, 120, 120, 255 },
|
.color = { 120, 120, 120, 255 },
|
||||||
.cornerRadius = 8,
|
.cornerRadius = CLAY_CORNER_RADIUS(8),
|
||||||
})
|
})
|
||||||
) {
|
) {
|
||||||
CLAY_TEXT(document.title, CLAY_TEXT_CONFIG({
|
CLAY_TEXT(document.title, CLAY_TEXT_CONFIG({
|
||||||
@ -252,7 +252,7 @@ int main(void) {
|
|||||||
Clay_Hovered()
|
Clay_Hovered()
|
||||||
? CLAY_RECTANGLE({
|
? CLAY_RECTANGLE({
|
||||||
.color = { 120, 120, 120, 120 },
|
.color = { 120, 120, 120, 120 },
|
||||||
.cornerRadius = 8
|
.cornerRadius = CLAY_CORNER_RADIUS(8)
|
||||||
})
|
})
|
||||||
: 0
|
: 0
|
||||||
) {
|
) {
|
||||||
|
24
fuzz/fuzzing_target.c
Normal file
24
fuzz/fuzzing_target.c
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
#include "clay.h"
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <stddef.h>
|
||||||
|
|
||||||
|
extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
|
||||||
|
if (size < sizeof(Clay_String)) return 0;
|
||||||
|
|
||||||
|
Clay_String testString = { .length = size, .chars = (const char *)data };
|
||||||
|
|
||||||
|
Clay_Dimensions dimensions = MeasureText(&testString, NULL);
|
||||||
|
|
||||||
|
// Call other critical functions
|
||||||
|
Clay_Arena arena = Clay_CreateArenaWithCapacityAndMemory(1024, (void*)data);
|
||||||
|
Clay_Initialize(arena, (Clay_Dimensions){1024, 768});
|
||||||
|
Clay_SetPointerState((Clay_Vector2){0, 0}, false);
|
||||||
|
Clay_BeginLayout();
|
||||||
|
Clay_EndLayout();
|
||||||
|
|
||||||
|
// Handle pointer state changes
|
||||||
|
Clay_SetPointerState((Clay_Vector2){1, 1}, true);
|
||||||
|
Clay_SetPointerState((Clay_Vector2){2, 2}, false);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
@ -87,10 +87,8 @@ Ray GetScreenToWorldPointWithZDistance(Vector2 position, Camera camera, int scre
|
|||||||
return ray;
|
return ray;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t measureCalls = 0;
|
|
||||||
|
|
||||||
static inline Clay_Dimensions Raylib_MeasureText(Clay_StringSlice text, Clay_TextElementConfig *config, uintptr_t userData) {
|
static inline Clay_Dimensions Raylib_MeasureText(Clay_StringSlice text, Clay_TextElementConfig *config, uintptr_t userData) {
|
||||||
measureCalls++;
|
|
||||||
// Measure string size for Font
|
// Measure string size for Font
|
||||||
Clay_Dimensions textSize = { 0 };
|
Clay_Dimensions textSize = { 0 };
|
||||||
|
|
||||||
@ -99,6 +97,9 @@ static inline Clay_Dimensions Raylib_MeasureText(Clay_StringSlice text, Clay_Tex
|
|||||||
|
|
||||||
float textHeight = config->fontSize;
|
float textHeight = config->fontSize;
|
||||||
Font fontToUse = Raylib_fonts[config->fontId].font;
|
Font fontToUse = Raylib_fonts[config->fontId].font;
|
||||||
|
// Font failed to load, likely the fonts are in the wrong place relative to the execution dir
|
||||||
|
if (!fontToUse.glyphs) return textSize;
|
||||||
|
|
||||||
float scaleFactor = config->fontSize/(float)fontToUse.baseSize;
|
float scaleFactor = config->fontSize/(float)fontToUse.baseSize;
|
||||||
|
|
||||||
for (int i = 0; i < text.length; ++i)
|
for (int i = 0; i < text.length; ++i)
|
||||||
@ -129,7 +130,6 @@ void Clay_Raylib_Initialize(int width, int height, const char *title, unsigned i
|
|||||||
|
|
||||||
void Clay_Raylib_Render(Clay_RenderCommandArray renderCommands)
|
void Clay_Raylib_Render(Clay_RenderCommandArray renderCommands)
|
||||||
{
|
{
|
||||||
measureCalls = 0;
|
|
||||||
for (int j = 0; j < renderCommands.length; j++)
|
for (int j = 0; j < renderCommands.length; j++)
|
||||||
{
|
{
|
||||||
Clay_RenderCommand *renderCommand = Clay_RenderCommandArray_Get(&renderCommands, j);
|
Clay_RenderCommand *renderCommand = Clay_RenderCommandArray_Get(&renderCommands, j);
|
||||||
|
Loading…
Reference in New Issue
Block a user