Added skinning and extend customization
Previous visual changes in the library were quite limited with some colors and some global properties. This commit changes all that and provides way more control over every widgets visual appearance. Changes include extended color selection, per widget properties and the possibility to use skinning. While the new API allows for a lot more control it is currently quite low level and needs a lot more testing and probably another higher level style API to make changes in code easier. I also had to remove the style modification code inside the demo and will probably first try to write another higher level API before adding it back in. This commit also include some breaking changes to existing code like the missing style stack API and some widget names changes due to added granularity granted by the rewritten style.
This commit is contained in:
parent
f9ea095e77
commit
fcba0e676b
|
@ -13,11 +13,11 @@ render backends it only focuses on the actual UI.
|
|||
## Features
|
||||
- Immediate mode graphical user interface toolkit
|
||||
- Written in C89 (ANSI C)
|
||||
- Small codebase (~11kLOC)
|
||||
- Small codebase (~12kLOC)
|
||||
- Focus on portability, efficiency and simplicity
|
||||
- No dependencies (not even the standard library)
|
||||
- No global or hidden state
|
||||
- Configurable style and colors
|
||||
- Fully skinnable and customizable
|
||||
- UTF-8 support
|
||||
|
||||
## Optional
|
||||
|
|
|
@ -228,7 +228,8 @@ device_draw(struct device *dev, struct zr_context *ctx, enum zr_anti_aliasing AA
|
|||
config.shape_AA = AA;
|
||||
config.line_AA = AA;
|
||||
config.circle_segment_count = 22;
|
||||
config.line_thickness = 1.0f;
|
||||
config.arc_segment_count = 22;
|
||||
config.curve_segment_count = 22;
|
||||
config.null = dev->null;
|
||||
|
||||
/* convert from command into hardware format */
|
|
@ -1,33 +0,0 @@
|
|||
# Install
|
||||
BIN = demo
|
||||
|
||||
# Compiler
|
||||
CC = clang
|
||||
DCC = gcc
|
||||
|
||||
# Flags
|
||||
CFLAGS = -std=c89 -pedantic
|
||||
|
||||
SRC = ../../zahnrad.c allegro.c
|
||||
OBJ = $(SRC:.c=.o)
|
||||
|
||||
ifeq ($(OS),Windows_NT)
|
||||
BIN := $(BIN).exe
|
||||
LIBS = -lmingw32 -lallegro -lallegro_primitives -lallegro_font -lallegro_ttf -lm
|
||||
else
|
||||
LIBS = -lallegro -lallegro_primitives -lallegro_font -lallegro_ttf -lGL -lm -lGLU -lGLEW
|
||||
endif
|
||||
|
||||
# Modes
|
||||
.PHONY: gcc
|
||||
gcc: CC = gcc
|
||||
gcc: $(BIN)
|
||||
|
||||
.PHONY: clang
|
||||
clang: CC = clang
|
||||
clang: $(BIN)
|
||||
|
||||
$(BIN):
|
||||
@mkdir -p bin
|
||||
rm -f bin/$(BIN) $(OBJS)
|
||||
$(CC) $(SRC) $(CFLAGS) -o bin/$(BIN) $(LIBS)
|
|
@ -1,267 +0,0 @@
|
|||
/*
|
||||
Copyright (c) 2016 Micha Mettke
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdint.h>
|
||||
#include <stdarg.h>
|
||||
#include <string.h>
|
||||
#include <math.h>
|
||||
#include <assert.h>
|
||||
#include <math.h>
|
||||
|
||||
#include <allegro5/allegro.h>
|
||||
#include <allegro5/allegro_primitives.h>
|
||||
#include <allegro5/allegro_font.h>
|
||||
#include <allegro5/allegro_ttf.h>
|
||||
|
||||
/* macros */
|
||||
#define DEMO_DO_NOT_DRAW_IMAGES
|
||||
#include "../../zahnrad.h"
|
||||
#include "../demo.c"
|
||||
|
||||
static void
|
||||
die(const char *fmt, ...)
|
||||
{
|
||||
va_list ap;
|
||||
va_start(ap, fmt);
|
||||
vfprintf(stderr, fmt, ap);
|
||||
va_end(ap);
|
||||
fputs("\n", stderr);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
static void
|
||||
draw(struct zr_context *ctx, int width, int height)
|
||||
{
|
||||
const struct zr_command *cmd;
|
||||
zr_foreach(cmd, ctx) {
|
||||
switch (cmd->type) {
|
||||
case ZR_COMMAND_NOP: break;
|
||||
case ZR_COMMAND_SCISSOR: {
|
||||
const struct zr_command_scissor *s = zr_command(scissor, cmd);
|
||||
al_set_clipping_rectangle(s->x-1,s->y-1,s->w+2, s->h+2);
|
||||
} break;
|
||||
case ZR_COMMAND_LINE: {
|
||||
const struct zr_command_line *l = zr_command(line, cmd);
|
||||
al_draw_line(l->begin.x, l->begin.y, l->end.x, l->end.y,
|
||||
al_map_rgba(l->color.r, l->color.g, l->color.b, l->color.a), 1.0f);
|
||||
} break;
|
||||
case ZR_COMMAND_RECT: {
|
||||
const struct zr_command_rect *r = zr_command(rect, cmd);
|
||||
al_draw_filled_rounded_rectangle(r->x, r->y, r->x + r->w, r->y + r->h,
|
||||
r->rounding, r->rounding,
|
||||
al_map_rgba(r->color.r, r->color.g, r->color.b, r->color.a));
|
||||
} break;
|
||||
case ZR_COMMAND_CIRCLE: {
|
||||
const struct zr_command_circle *c = zr_command(circle, cmd);
|
||||
al_draw_filled_circle(c->x + c->w/2, c->y + c->w/2, c->w/2,
|
||||
al_map_rgba(c->color.r, c->color.g, c->color.b, c->color.a));
|
||||
} break;
|
||||
case ZR_COMMAND_TRIANGLE: {
|
||||
const struct zr_command_triangle *t = zr_command(triangle, cmd);
|
||||
al_draw_filled_triangle(t->a.x, t->a.y, t->b.x, t->b.y, t->c.x, t->c.y,
|
||||
al_map_rgba(t->color.r, t->color.g, t->color.b, t->color.a));
|
||||
} break;
|
||||
case ZR_COMMAND_TEXT: {
|
||||
const struct zr_command_text *t = zr_command(text, cmd);
|
||||
ALLEGRO_FONT *font = t->font->userdata.ptr;
|
||||
al_draw_text(font, al_map_rgba(t->foreground.r, t->foreground.g, t->foreground.g, t->foreground.a),
|
||||
t->x, t->y, ALLEGRO_ALIGN_LEFT, t->string);
|
||||
} break;
|
||||
case ZR_COMMAND_CURVE: {
|
||||
unsigned int i_step;
|
||||
float t_step;
|
||||
const struct zr_command_curve *q = zr_command(curve, cmd);
|
||||
struct zr_vec2i last = q->begin;
|
||||
struct zr_vec2i p1 = q->begin;
|
||||
struct zr_vec2i p2 = q->ctrl[0];
|
||||
struct zr_vec2i p3 = q->ctrl[1];
|
||||
struct zr_vec2i p4 = q->end;
|
||||
t_step = 1.0f/(float)22.0f;
|
||||
for (i_step = 1; i_step <= 22.0f; ++i_step) {
|
||||
float t = t_step * (float)i_step;
|
||||
float u = 1.0f - t;
|
||||
float w1 = u*u*u;
|
||||
float w2 = 3*u*u*t;
|
||||
float w3 = 3*u*t*t;
|
||||
float w4 = t * t *t;
|
||||
float x = w1 * p1.x + w2 * p2.x + w3 * p3.x + w4 * p4.x;
|
||||
float y = w1 * p1.y + w2 * p2.y + w3 * p3.y + w4 * p4.y;
|
||||
al_draw_line(last.x, last.y, x, y,
|
||||
al_map_rgba(q->color.r, q->color.g, q->color.b, q->color.a), 1.0f);
|
||||
last.x = (short)x; last.y = (short)y;
|
||||
}
|
||||
} break;
|
||||
case ZR_COMMAND_ARC:
|
||||
case ZR_COMMAND_IMAGE:
|
||||
default: break;
|
||||
}
|
||||
}
|
||||
zr_clear(ctx);
|
||||
al_set_clipping_rectangle(0,0,width, height);
|
||||
}
|
||||
|
||||
static size_t
|
||||
font_get_width(zr_handle handle, float height, const char *text, size_t len)
|
||||
{
|
||||
/* <heavy sign> allegro does not support text width calculation
|
||||
* for strings that are not zero terminated... Therefore I have to
|
||||
* allocate a string every time.
|
||||
* OPT: maybe use a buffer to copy into? */
|
||||
const ALLEGRO_FONT *font = handle.ptr;
|
||||
ALLEGRO_USTR *str = al_ustr_new_from_buffer(text, len);
|
||||
size_t width = (size_t)al_get_ustr_width(font, str);
|
||||
UNUSED(height);
|
||||
al_ustr_free(str);
|
||||
return width;
|
||||
}
|
||||
|
||||
static void
|
||||
input_key(struct zr_context *ctx, ALLEGRO_EVENT *evt, int down)
|
||||
{
|
||||
int sym = evt->keyboard.keycode;
|
||||
if (sym == ALLEGRO_KEY_RSHIFT || sym == ALLEGRO_KEY_LSHIFT)
|
||||
zr_input_key(ctx, ZR_KEY_SHIFT, down);
|
||||
else if (sym == ALLEGRO_KEY_DELETE)
|
||||
zr_input_key(ctx, ZR_KEY_DEL, down);
|
||||
else if (sym == ALLEGRO_KEY_ENTER)
|
||||
zr_input_key(ctx, ZR_KEY_ENTER, down);
|
||||
else if (sym == ALLEGRO_KEY_TAB)
|
||||
zr_input_key(ctx, ZR_KEY_TAB, down);
|
||||
else if (sym == ALLEGRO_KEY_BACKSPACE)
|
||||
zr_input_key(ctx, ZR_KEY_BACKSPACE, down);
|
||||
else if (sym == ALLEGRO_KEY_LEFT)
|
||||
zr_input_key(ctx, ZR_KEY_LEFT, down);
|
||||
else if (sym == ALLEGRO_KEY_RIGHT)
|
||||
zr_input_key(ctx, ZR_KEY_RIGHT, down);
|
||||
else if (sym == ALLEGRO_KEY_C)
|
||||
zr_input_key(ctx, ZR_KEY_COPY, down && evt->keyboard.modifiers & ALLEGRO_KEYMOD_CTRL);
|
||||
else if (sym == ALLEGRO_KEY_V)
|
||||
zr_input_key(ctx, ZR_KEY_PASTE, down && evt->keyboard.modifiers & ALLEGRO_KEYMOD_CTRL);
|
||||
else if (sym == ALLEGRO_KEY_X)
|
||||
zr_input_key(ctx, ZR_KEY_CUT, down && evt->keyboard.modifiers & ALLEGRO_KEYMOD_CTRL);
|
||||
}
|
||||
|
||||
static void
|
||||
input_button(struct zr_context *ctx, ALLEGRO_EVENT *evt, int down)
|
||||
{
|
||||
const int x = evt->mouse.x;
|
||||
const int y = evt->mouse.y;
|
||||
if (evt->mouse.button == 1)
|
||||
zr_input_button(ctx, ZR_BUTTON_LEFT, x, y, down);
|
||||
if (evt->mouse.button == 2)
|
||||
zr_input_button(ctx, ZR_BUTTON_RIGHT, x, y, down);
|
||||
}
|
||||
|
||||
static void* mem_alloc(zr_handle unused, size_t size)
|
||||
{UNUSED(unused); return calloc(1, size);}
|
||||
static void mem_free(zr_handle unused, void *ptr)
|
||||
{UNUSED(unused); free(ptr);}
|
||||
|
||||
int
|
||||
main(int argc, char *argv[])
|
||||
{
|
||||
/* Platform */
|
||||
const char *font_path;
|
||||
int width = 0, height = 0;
|
||||
int running = 1;
|
||||
|
||||
ALLEGRO_DISPLAY *display;
|
||||
ALLEGRO_EVENT_QUEUE *queue;
|
||||
ALLEGRO_FONT *font;
|
||||
struct demo gui;
|
||||
|
||||
font_path = argv[1];
|
||||
if (argc < 2)
|
||||
die("Missing TTF Font file argument!");
|
||||
|
||||
/* Allegro */
|
||||
al_init();
|
||||
al_init_font_addon();
|
||||
al_init_ttf_addon();
|
||||
al_install_keyboard();
|
||||
al_install_mouse();
|
||||
al_init_primitives_addon();
|
||||
display = al_create_display(WINDOW_WIDTH, WINDOW_HEIGHT);
|
||||
al_set_window_title(display, "Zahnrad");
|
||||
queue = al_create_event_queue();
|
||||
al_register_event_source(queue, al_get_display_event_source(display));
|
||||
al_register_event_source(queue, al_get_keyboard_event_source());
|
||||
al_register_event_source(queue, al_get_mouse_event_source());
|
||||
font = al_load_ttf_font(font_path, 14, 0);
|
||||
if (!font) die("Failed to load font: %s\n", font_path);
|
||||
|
||||
{
|
||||
/* GUI */
|
||||
struct zr_user_font usrfnt;
|
||||
struct zr_allocator alloc;
|
||||
alloc.userdata.ptr = NULL;
|
||||
alloc.alloc = mem_alloc;
|
||||
alloc.free = mem_free;
|
||||
|
||||
usrfnt.userdata = zr_handle_ptr(font);
|
||||
usrfnt.width = font_get_width;
|
||||
usrfnt.height = al_get_font_line_height(font);
|
||||
zr_init(&gui.ctx, &alloc, &usrfnt);
|
||||
}
|
||||
|
||||
while (running) {
|
||||
/* Input */
|
||||
ALLEGRO_EVENT evt;
|
||||
zr_input_begin(&gui.ctx);
|
||||
while (al_get_next_event(queue, &evt)) {
|
||||
if (evt.type == ALLEGRO_EVENT_DISPLAY_CLOSE) goto cleanup;
|
||||
else if (evt.type == ALLEGRO_EVENT_KEY_UP && evt.keyboard.display == display)
|
||||
input_key(&gui.ctx, &evt, zr_false);
|
||||
else if (evt.type == ALLEGRO_EVENT_KEY_DOWN && evt.keyboard.display == display)
|
||||
input_key(&gui.ctx, &evt, zr_true);
|
||||
else if (evt.type == ALLEGRO_EVENT_MOUSE_BUTTON_DOWN)
|
||||
input_button(&gui.ctx, &evt, zr_true);
|
||||
else if (evt.type == ALLEGRO_EVENT_MOUSE_BUTTON_UP)
|
||||
input_button(&gui.ctx, &evt, zr_false);
|
||||
else if (evt.type == ALLEGRO_EVENT_MOUSE_AXES) {
|
||||
zr_input_motion(&gui.ctx, evt.mouse.x, evt.mouse.y);
|
||||
} else if (evt.type == ALLEGRO_EVENT_KEY_CHAR) {
|
||||
if (evt.keyboard.display == display)
|
||||
if (evt.keyboard.unichar > 0 && evt.keyboard.unichar < 0x10000)
|
||||
zr_input_unicode(&gui.ctx, (zr_rune)evt.keyboard.unichar);
|
||||
}
|
||||
}
|
||||
zr_input_end(&gui.ctx);
|
||||
|
||||
/* GUI */
|
||||
width = al_get_display_width(display);
|
||||
height = al_get_display_height(display);
|
||||
running = run_demo(&gui);
|
||||
|
||||
/* Draw */
|
||||
al_clear_to_color(al_map_rgba_f(0.2f, 0.2f, 0.2f, 1.0f));
|
||||
draw(&gui.ctx, width, height);
|
||||
al_flip_display();
|
||||
}
|
||||
|
||||
cleanup:
|
||||
/* Cleanup */
|
||||
if (queue) al_destroy_event_queue(queue);
|
||||
if (display) al_destroy_display(display);
|
||||
zr_free(&gui.ctx);
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -459,7 +459,8 @@ static void mem_free(zr_handle unused, void* ptr)
|
|||
config.shape_AA = ZR_ANTI_ALIASING_ON;
|
||||
config.line_AA = ZR_ANTI_ALIASING_ON;
|
||||
config.circle_segment_count = 22;
|
||||
config.line_thickness = 1.0f;
|
||||
config.curve_segment_count = 22;
|
||||
config.arc_segment_count = 22;
|
||||
config.null = nullTexture;
|
||||
|
||||
// setup buffers to load vertices and elements
|
||||
|
|
957
demo/demo.c
957
demo/demo.c
File diff suppressed because it is too large
Load Diff
|
@ -396,7 +396,8 @@ device_draw(struct device *dev, struct zr_context *ctx, int width, int height,
|
|||
config.shape_AA = AA;
|
||||
config.line_AA = AA;
|
||||
config.circle_segment_count = 22;
|
||||
config.line_thickness = 1.0f;
|
||||
config.curve_segment_count = 22;
|
||||
config.arc_segment_count = 22;
|
||||
config.null = dev->null;
|
||||
|
||||
/* setup buffers to load vertices and elements */
|
||||
|
|
|
@ -569,7 +569,8 @@ device_draw(struct device *dev, struct zr_context *ctx, int width, int height,
|
|||
config.shape_AA = AA;
|
||||
config.line_AA = AA;
|
||||
config.circle_segment_count = 22;
|
||||
config.line_thickness = 1.0f;
|
||||
config.arc_segment_count = 22;
|
||||
config.curve_segment_count = 22;
|
||||
config.null = dev->null;
|
||||
|
||||
/* setup buffers to load vertices and elements */
|
||||
|
|
|
@ -122,8 +122,6 @@ icon_load(const char *filename)
|
|||
glBindTexture(GL_TEXTURE_2D, tex);
|
||||
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_NEAREST);
|
||||
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR_MIPMAP_NEAREST);
|
||||
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
|
||||
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, x, y, 0, GL_RGBA, GL_UNSIGNED_BYTE, data);
|
||||
glGenerateMipmap(GL_TEXTURE_2D);
|
||||
stbi_image_free(data);
|
||||
|
@ -363,7 +361,6 @@ device_draw(struct device *dev, struct zr_context *ctx, int width, int height,
|
|||
glUseProgram(dev->prog);
|
||||
glUniform1i(dev->uniform_tex, 0);
|
||||
glUniformMatrix4fv(dev->uniform_proj, 1, GL_FALSE, &ortho[0][0]);
|
||||
|
||||
{
|
||||
/* convert from command queue into draw list and draw to screen */
|
||||
const struct zr_draw_command *cmd;
|
||||
|
@ -387,12 +384,13 @@ device_draw(struct device *dev, struct zr_context *ctx, int width, int height,
|
|||
/* fill converting configuration */
|
||||
struct zr_convert_config config;
|
||||
memset(&config, 0, sizeof(config));
|
||||
config.circle_segment_count = 22;
|
||||
config.arc_segment_count = 22;
|
||||
config.curve_segment_count = 22;
|
||||
config.global_alpha = 1.0f;
|
||||
config.null = dev->null;
|
||||
config.shape_AA = AA;
|
||||
config.line_AA = AA;
|
||||
config.circle_segment_count = 22;
|
||||
config.line_thickness = 1.0f;
|
||||
config.null = dev->null;
|
||||
|
||||
/* setup buffers to load vertices and elements */
|
||||
zr_buffer_init_fixed(&vbuf, vertices, MAX_VERTEX_MEMORY);
|
||||
|
@ -414,7 +412,6 @@ device_draw(struct device *dev, struct zr_context *ctx, int width, int height,
|
|||
}
|
||||
zr_clear(ctx);
|
||||
}
|
||||
|
||||
/* restore old state */
|
||||
glUseProgram((GLuint)last_prog);
|
||||
glBindTexture(GL_TEXTURE_2D, (GLuint)last_tex);
|
||||
|
@ -422,6 +419,7 @@ device_draw(struct device *dev, struct zr_context *ctx, int width, int height,
|
|||
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, (GLuint)last_ebo);
|
||||
glBindVertexArray((GLuint)last_vao);
|
||||
glDisable(GL_SCISSOR_TEST);
|
||||
glDisable(GL_BLEND);
|
||||
}
|
||||
|
||||
static void
|
||||
|
|
256
demo/x11/xlib.c
256
demo/x11/xlib.c
|
@ -40,50 +40,6 @@
|
|||
#define DEMO_DO_NOT_USE_COLOR_PICKER
|
||||
#include "../demo.c"
|
||||
|
||||
#if 0
|
||||
|
||||
#ifdef __clang__
|
||||
#pragma clang diagnostic push
|
||||
#pragma clang diagnostic ignored "-Wsign-conversion"
|
||||
#pragma clang diagnostic ignored "-Wfloat-equal"
|
||||
#pragma clang diagnostic ignored "-Wbad-function-cast"
|
||||
#pragma clang diagnostic ignored "-Wcast-qual"
|
||||
#pragma clang diagnostic ignored "-Wshadow"
|
||||
#pragma clang diagnostic ignored "-Wmissing-field-initializers"
|
||||
#pragma clang diagnostic ignored "-Wdeclaration-after-statement"
|
||||
#pragma clang diagnostic ignored "-Wunused-function"
|
||||
#pragma clang diagnostic ignored "-Wdisabled-macro-expansion"
|
||||
#elif defined(__GNUC__) || defined(__GNUG__)
|
||||
#pragma GCC diagnostic push
|
||||
#pragma GCC diagnostic ignored "-Wfloat-equal"
|
||||
#pragma GCC diagnostic ignored "-Wsign-conversion"
|
||||
#pragma GCC diagnostic ignored "-Wconversion"
|
||||
#pragma GCC diagnostic ignored "-Wbad-function-cast"
|
||||
#pragma GCC diagnostic ignored "-Wcast-qual"
|
||||
#pragma GCC diagnostic ignored "-Wshadow"
|
||||
#pragma GCC diagnostic ignored "-Wmissing-field-initializers"
|
||||
#pragma GCC diagnostic ignored "-Wdeclaration-after-statement"
|
||||
#pragma GCC diagnostic ignored "-Wtype-limits"
|
||||
#pragma GCC diagnostic ignored "-Wswitch-default"
|
||||
#pragma GCC diagnostic ignored "-Wunused-function"
|
||||
#elif _MSC_VER
|
||||
#pragma warning (push)
|
||||
#pragma warning (disable: 4456)
|
||||
#endif
|
||||
|
||||
#define STB_IMAGE_IMPLEMENTATION
|
||||
#include "../stb_image.h"
|
||||
|
||||
#ifdef __clang__
|
||||
#pragma clang diagnostic pop
|
||||
#elif defined(__GNUC__) || defined(__GNUG__)
|
||||
#pragma GCC diagnostic pop
|
||||
#elif _MSC_VER
|
||||
#pragma warning (pop)
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
typedef struct XFont XFont;
|
||||
typedef struct XSurface XSurface;
|
||||
typedef struct XWindow XWindow;
|
||||
|
@ -275,17 +231,51 @@ surface_scissor(XSurface *surf, float x, float y, float w, float h)
|
|||
}
|
||||
|
||||
static void
|
||||
surface_draw_line(XSurface *surf, int16_t x0, int16_t y0, int16_t x1,
|
||||
int16_t y1, struct zr_color col)
|
||||
surface_stroke_line(XSurface *surf, short x0, short y0, short x1,
|
||||
short y1, unsigned int line_thickness, struct zr_color col)
|
||||
{
|
||||
unsigned long c = color_from_byte(&col.r);
|
||||
XSetForeground(surf->dpy, surf->gc, c);
|
||||
XSetLineAttributes(surf->dpy, surf->gc, line_thickness, LineSolid, CapButt, JoinMiter);
|
||||
XDrawLine(surf->dpy, surf->drawable, surf->gc, (int)x0, (int)y0, (int)x1, (int)y1);
|
||||
XSetLineAttributes(surf->dpy, surf->gc, 1, LineSolid, CapButt, JoinMiter);
|
||||
}
|
||||
|
||||
static void
|
||||
surface_draw_rect(XSurface* surf, int16_t x, int16_t y, uint16_t w,
|
||||
uint16_t h, uint16_t r, struct zr_color col)
|
||||
surface_stroke_rect(XSurface* surf, short x, short y, unsigned short w,
|
||||
unsigned short h, unsigned short r, unsigned short line_thickness, struct zr_color col)
|
||||
{
|
||||
unsigned long c = color_from_byte(&col.r);
|
||||
XSetForeground(surf->dpy, surf->gc, c);
|
||||
XSetLineAttributes(surf->dpy, surf->gc, line_thickness, LineSolid, CapButt, JoinMiter);
|
||||
if (r == 0) {
|
||||
XFillRectangle(surf->dpy, surf->drawable, surf->gc, x, y, w, h);
|
||||
} else {
|
||||
short xc = x + r;
|
||||
short yc = y + r;
|
||||
short wc = (short)(w - 2 * r);
|
||||
short hc = (short)(h - 2 * r);
|
||||
|
||||
XDrawLine(surf->dpy, surf->drawable, surf->gc, xc, y, xc+wc, y);
|
||||
XDrawLine(surf->dpy, surf->drawable, surf->gc, x+w, yc, x+w, yc+wc);
|
||||
XDrawLine(surf->dpy, surf->drawable, surf->gc, xc, y+h, xc+wc, y+h);
|
||||
XDrawLine(surf->dpy, surf->drawable, surf->gc, x, yc, yc+hc, x);
|
||||
|
||||
XFillArc(surf->dpy, surf->drawable, surf->gc, xc + wc - r, y,
|
||||
(unsigned)r*2, (unsigned)r*2, 0 * 64, 90 * 64);
|
||||
XFillArc(surf->dpy, surf->drawable, surf->gc, x, y,
|
||||
(unsigned)r*2, (unsigned)r*2, 90 * 64, 90 * 64);
|
||||
XFillArc(surf->dpy, surf->drawable, surf->gc, x, yc + hc - r,
|
||||
(unsigned)r*2, (unsigned)2*r, 180 * 64, 90 * 64);
|
||||
XFillArc(surf->dpy, surf->drawable, surf->gc, xc + wc - r, yc + hc - r,
|
||||
(unsigned)r*2, (unsigned)2*r, -90 * 64, 90 * 64);
|
||||
}
|
||||
XSetLineAttributes(surf->dpy, surf->gc, 1, LineSolid, CapButt, JoinMiter);
|
||||
}
|
||||
|
||||
static void
|
||||
surface_fill_rect(XSurface* surf, short x, short y, unsigned short w,
|
||||
unsigned short h, unsigned short r, struct zr_color col)
|
||||
{
|
||||
unsigned long c = color_from_byte(&col.r);
|
||||
XSetForeground(surf->dpy, surf->gc, c);
|
||||
|
@ -339,8 +329,8 @@ surface_draw_rect(XSurface* surf, int16_t x, int16_t y, uint16_t w,
|
|||
}
|
||||
|
||||
static void
|
||||
surface_draw_triangle(XSurface *surf, int16_t x0, int16_t y0, int16_t x1,
|
||||
int16_t y1, int16_t x2, int16_t y2, struct zr_color col)
|
||||
surface_fill_triangle(XSurface *surf, short x0, short y0, short x1,
|
||||
short y1, short x2, short y2, struct zr_color col)
|
||||
{
|
||||
XPoint pnts[3];
|
||||
unsigned long c = color_from_byte(&col.r);
|
||||
|
@ -355,43 +345,65 @@ surface_draw_triangle(XSurface *surf, int16_t x0, int16_t y0, int16_t x1,
|
|||
}
|
||||
|
||||
static void
|
||||
surface_draw_polygon(XSurface *surf, enum zr_command_drawing_mode type,
|
||||
const struct zr_vec2i *pnts, int count, struct zr_color col)
|
||||
surface_stroke_triangle(XSurface *surf, short x0, short y0, short x1,
|
||||
short y1, short x2, short y2, unsigned short line_thickness, struct zr_color col)
|
||||
{
|
||||
XPoint pnts[3];
|
||||
unsigned long c = color_from_byte(&col.r);
|
||||
XSetLineAttributes(surf->dpy, surf->gc, line_thickness, LineSolid, CapButt, JoinMiter);
|
||||
XDrawLine(surf->dpy, surf->drawable, surf->gc, x0, y0, x1, y1);
|
||||
XDrawLine(surf->dpy, surf->drawable, surf->gc, x1, y1, x2, y2);
|
||||
XDrawLine(surf->dpy, surf->drawable, surf->gc, x2, y2, x0, y0);
|
||||
XSetLineAttributes(surf->dpy, surf->gc, 1, LineSolid, CapButt, JoinMiter);
|
||||
}
|
||||
|
||||
static void
|
||||
surface_fill_polygon(XSurface *surf, const struct zr_vec2i *pnts, int count,
|
||||
struct zr_color col)
|
||||
{
|
||||
int i = 0;
|
||||
#define MAX_POINTS 64
|
||||
XPoint xpnts[MAX_POINTS];
|
||||
unsigned long c = color_from_byte(&col.r);
|
||||
XSetForeground(surf->dpy, surf->gc, c);
|
||||
for (i = 0; i < count && i < MAX_POINTS; ++i) {
|
||||
xpnts[i].x = pnts[i].x;
|
||||
xpnts[i].y = pnts[i].y;
|
||||
}
|
||||
XFillPolygon(surf->dpy, surf->drawable, surf->gc, xpnts, count, Convex, CoordModeOrigin);
|
||||
#undef MAX_POINTS
|
||||
}
|
||||
|
||||
static void
|
||||
surface_stroke_polygon(XSurface *surf, const struct zr_vec2i *pnts, int count,
|
||||
unsigned short line_thickness, struct zr_color col)
|
||||
{
|
||||
int i = 0;
|
||||
unsigned long c = color_from_byte(&col.r);
|
||||
XSetForeground(surf->dpy, surf->gc, c);
|
||||
if (type == ZR_FILLED) {
|
||||
#define MAX_POINTS 64
|
||||
XPoint xpnts[MAX_POINTS];
|
||||
|
||||
for (i = 0; i < count && i < MAX_POINTS; ++i) {
|
||||
xpnts[i].x = pnts[i].x;
|
||||
xpnts[i].y = pnts[i].y;
|
||||
}
|
||||
XFillPolygon(surf->dpy, surf->drawable, surf->gc, xpnts, count, Convex, CoordModeOrigin);
|
||||
#undef MAX_POINTS
|
||||
} else {
|
||||
for (i = 1; i < count; ++i)
|
||||
XDrawLine(surf->dpy, surf->drawable, surf->gc, pnts[i-1].x, pnts[i-1].y, pnts[i].x, pnts[i].y);
|
||||
XDrawLine(surf->dpy, surf->drawable, surf->gc, pnts[count-1].x, pnts[count-1].y, pnts[0].x, pnts[0].y);
|
||||
}
|
||||
XSetLineAttributes(surf->dpy, surf->gc, line_thickness, LineSolid, CapButt, JoinMiter);
|
||||
for (i = 1; i < count; ++i)
|
||||
XDrawLine(surf->dpy, surf->drawable, surf->gc, pnts[i-1].x, pnts[i-1].y, pnts[i].x, pnts[i].y);
|
||||
XDrawLine(surf->dpy, surf->drawable, surf->gc, pnts[count-1].x, pnts[count-1].y, pnts[0].x, pnts[0].y);
|
||||
XSetLineAttributes(surf->dpy, surf->gc, 1, LineSolid, CapButt, JoinMiter);
|
||||
}
|
||||
|
||||
static void
|
||||
surface_draw_polyline(XSurface *surf,
|
||||
const struct zr_vec2i *pnts, int count, struct zr_color col)
|
||||
surface_stroke_polyline(XSurface *surf, const struct zr_vec2i *pnts,
|
||||
int count, unsigned short line_thickness, struct zr_color col)
|
||||
{
|
||||
int i = 0;
|
||||
unsigned long c = color_from_byte(&col.r);
|
||||
XSetLineAttributes(surf->dpy, surf->gc, line_thickness, LineSolid, CapButt, JoinMiter);
|
||||
XSetForeground(surf->dpy, surf->gc, c);
|
||||
for (i = 0; i < count-1; ++i)
|
||||
XDrawLine(surf->dpy, surf->drawable, surf->gc, pnts[i].x, pnts[i].y, pnts[i+1].x, pnts[i+1].y);
|
||||
XSetLineAttributes(surf->dpy, surf->gc, 1, LineSolid, CapButt, JoinMiter);
|
||||
}
|
||||
|
||||
static void
|
||||
surface_draw_circle(XSurface *surf, int16_t x, int16_t y, uint16_t w,
|
||||
uint16_t h, struct zr_color col)
|
||||
surface_fill_circle(XSurface *surf, short x, short y, unsigned short w,
|
||||
unsigned short h, struct zr_color col)
|
||||
{
|
||||
unsigned long c = color_from_byte(&col.r);
|
||||
XSetForeground(surf->dpy, surf->gc, c);
|
||||
|
@ -400,14 +412,27 @@ surface_draw_circle(XSurface *surf, int16_t x, int16_t y, uint16_t w,
|
|||
}
|
||||
|
||||
static void
|
||||
surface_draw_curve(XSurface *surf, struct zr_vec2i p1,
|
||||
surface_stroke_circle(XSurface *surf, short x, short y, unsigned short w,
|
||||
unsigned short h, unsigned short line_thickness, struct zr_color col)
|
||||
{
|
||||
unsigned long c = color_from_byte(&col.r);
|
||||
XSetLineAttributes(surf->dpy, surf->gc, line_thickness, LineSolid, CapButt, JoinMiter);
|
||||
XSetForeground(surf->dpy, surf->gc, c);
|
||||
XDrawArc(surf->dpy, surf->drawable, surf->gc, (int)x, (int)y,
|
||||
(unsigned)w, (unsigned)h, 0, 360 * 64);
|
||||
XSetLineAttributes(surf->dpy, surf->gc, 1, LineSolid, CapButt, JoinMiter);
|
||||
}
|
||||
|
||||
static void
|
||||
surface_stroke_curve(XSurface *surf, struct zr_vec2i p1,
|
||||
struct zr_vec2i p2, struct zr_vec2i p3, struct zr_vec2i p4,
|
||||
unsigned int num_segments, struct zr_color col)
|
||||
unsigned int num_segments, unsigned short line_thickness, struct zr_color col)
|
||||
{
|
||||
unsigned int i_step;
|
||||
float t_step;
|
||||
struct zr_vec2i last = p1;
|
||||
|
||||
XSetLineAttributes(surf->dpy, surf->gc, line_thickness, LineSolid, CapButt, JoinMiter);
|
||||
num_segments = MAX(num_segments, 1);
|
||||
t_step = 1.0f/(float)num_segments;
|
||||
for (i_step = 1; i_step <= num_segments; ++i_step) {
|
||||
|
@ -419,13 +444,14 @@ surface_draw_curve(XSurface *surf, struct zr_vec2i p1,
|
|||
float w4 = t * t *t;
|
||||
float x = w1 * p1.x + w2 * p2.x + w3 * p3.x + w4 * p4.x;
|
||||
float y = w1 * p1.y + w2 * p2.y + w3 * p3.y + w4 * p4.y;
|
||||
surface_draw_line(surf, last.x, last.y, (short)x, (short)y, col);
|
||||
surface_stroke_line(surf, last.x, last.y, (short)x, (short)y, line_thickness,col);
|
||||
last.x = (short)x; last.y = (short)y;
|
||||
}
|
||||
XSetLineAttributes(surf->dpy, surf->gc, 1, LineSolid, CapButt, JoinMiter);
|
||||
}
|
||||
|
||||
static void
|
||||
surface_draw_text(XSurface *surf, int16_t x, int16_t y, uint16_t w, uint16_t h,
|
||||
surface_draw_text(XSurface *surf, short x, short y, unsigned short w, unsigned short h,
|
||||
const char *text, size_t len, XFont *font, struct zr_color cbg, struct zr_color cfg)
|
||||
{
|
||||
int tx, ty, th;
|
||||
|
@ -523,39 +549,6 @@ surface_del(XSurface *surf)
|
|||
free(surf);
|
||||
}
|
||||
|
||||
#if 0
|
||||
static XSurface*
|
||||
surface_load(const char *filename, Display *dpy, int screen, Window root)
|
||||
{
|
||||
GC gc;
|
||||
int x,y,n;
|
||||
XSurface *surf;
|
||||
XImage *xim;
|
||||
XGCValues gcvalues;
|
||||
|
||||
unsigned char *data = stbi_load(filename, &x, &y, &n, 0);
|
||||
if (!data) die("[XLIB]: failed to load image: %s", filename);
|
||||
surf = surface_create(dpy, screen, root, (unsigned int)x, (unsigned int)y);
|
||||
xim = XCreateImage(dpy, CopyFromParent, 32, ZPixmap, 0, (char*)data,
|
||||
(unsigned int)x, (unsigned int)y, 32, 0);
|
||||
if (!xim) die("[XLIB]: failed to create image from file: %s", filename);
|
||||
|
||||
gc = XCreateGC(dpy, surf->drawable, 0, &gcvalues);
|
||||
XPutImage(dpy, surf->drawable, gc, xim, 0, 0, 0, 0,
|
||||
(unsigned int)x, (unsigned int)y);
|
||||
XDestroyImage(xim);
|
||||
return surf;
|
||||
}
|
||||
|
||||
static struct zr_image
|
||||
icon_load(const char *filename, Display *dpy, int screen, Window root)
|
||||
{
|
||||
XSurface* surf = surface_load(filename, dpy, screen, root);
|
||||
return zr_image_ptr(surf);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
static void
|
||||
input_key(struct XWindow *xw, struct zr_context *ctx, XEvent *evt, int down)
|
||||
{
|
||||
|
@ -717,29 +710,48 @@ main(int argc, char *argv[])
|
|||
} break;
|
||||
case ZR_COMMAND_LINE: {
|
||||
const struct zr_command_line *l = zr_command(line, cmd);
|
||||
surface_draw_line(xw.surf, l->begin.x, l->begin.y, l->end.x,
|
||||
l->end.y, l->color);
|
||||
surface_stroke_line(xw.surf, l->begin.x, l->begin.y, l->end.x,
|
||||
l->end.y, l->line_thickness, l->color);
|
||||
} break;
|
||||
case ZR_COMMAND_RECT: {
|
||||
const struct zr_command_rect *r = zr_command(rect, cmd);
|
||||
surface_draw_rect(xw.surf, r->x, r->y, r->w, r->h, (uint16_t)r->rounding, r->color);
|
||||
surface_stroke_rect(xw.surf, r->x, r->y, r->w, r->h,
|
||||
(uint16_t)r->rounding, r->line_thickness, r->color);
|
||||
} break;
|
||||
case ZR_COMMAND_RECT_FILLED: {
|
||||
const struct zr_command_rect_filled *r = zr_command(rect_filled, cmd);
|
||||
surface_fill_rect(xw.surf, r->x, r->y, r->w, r->h,
|
||||
(uint16_t)r->rounding, r->color);
|
||||
} break;
|
||||
case ZR_COMMAND_CIRCLE: {
|
||||
const struct zr_command_circle *c = zr_command(circle, cmd);
|
||||
surface_draw_circle(xw.surf, c->x, c->y, c->w, c->h, c->color);
|
||||
surface_stroke_circle(xw.surf, c->x, c->y, c->w, c->h, c->line_thickness, c->color);
|
||||
} break;
|
||||
case ZR_COMMAND_CIRCLE_FILLED: {
|
||||
const struct zr_command_circle_filled *c = zr_command(circle_filled, cmd);
|
||||
surface_fill_circle(xw.surf, c->x, c->y, c->w, c->h, c->color);
|
||||
} break;
|
||||
case ZR_COMMAND_TRIANGLE: {
|
||||
const struct zr_command_triangle *t = zr_command(triangle, cmd);
|
||||
surface_draw_triangle(xw.surf, t->a.x, t->a.y, t->b.x, t->b.y,
|
||||
const struct zr_command_triangle*t = zr_command(triangle, cmd);
|
||||
surface_stroke_triangle(xw.surf, t->a.x, t->a.y, t->b.x, t->b.y,
|
||||
t->c.x, t->c.y, t->line_thickness, t->color);
|
||||
} break;
|
||||
case ZR_COMMAND_TRIANGLE_FILLED: {
|
||||
const struct zr_command_triangle_filled *t = zr_command(triangle_filled, cmd);
|
||||
surface_fill_triangle(xw.surf, t->a.x, t->a.y, t->b.x, t->b.y,
|
||||
t->c.x, t->c.y, t->color);
|
||||
} break;
|
||||
case ZR_COMMAND_POLYGON: {
|
||||
const struct zr_command_polygon *p = zr_command(polygon, cmd);
|
||||
surface_draw_polygon(xw.surf, p->mode, p->points, p->point_count, p->color);
|
||||
surface_stroke_polygon(xw.surf, p->points, p->point_count, p->line_thickness,p->color);
|
||||
} break;
|
||||
case ZR_COMMAND_POLYGON_FILLED: {
|
||||
const struct zr_command_polygon_filled *p = zr_command(polygon_filled, cmd);
|
||||
surface_fill_polygon(xw.surf, p->points, p->point_count, p->color);
|
||||
} break;
|
||||
case ZR_COMMAND_POLYLINE: {
|
||||
const struct zr_command_polyline *p = zr_command(polyline, cmd);
|
||||
surface_draw_polyline(xw.surf, p->points, p->point_count, p->color);
|
||||
surface_stroke_polyline(xw.surf, p->points, p->point_count, p->line_thickness, p->color);
|
||||
} break;
|
||||
case ZR_COMMAND_TEXT: {
|
||||
const struct zr_command_text *t = zr_command(text, cmd);
|
||||
|
@ -748,19 +760,15 @@ main(int argc, char *argv[])
|
|||
(XFont*)t->font->userdata.ptr,
|
||||
t->background, t->foreground);
|
||||
} break;
|
||||
case ZR_COMMAND_IMAGE: {
|
||||
const struct zr_command_image *img = zr_command(image, cmd);
|
||||
XSurface *surf = (XSurface*)img->img.handle.ptr;
|
||||
surface_blit(xw.surf, surf, img->x, img->y, img->w, img->h,
|
||||
0, 0, (int)surf->w, (int)surf->h);
|
||||
} break;
|
||||
case ZR_COMMAND_CURVE: {
|
||||
const struct zr_command_curve *q = zr_command(curve, cmd);
|
||||
surface_draw_curve(xw.surf, q->begin, q->ctrl[0], q->ctrl[1],
|
||||
q->end, 22, q->color);
|
||||
surface_stroke_curve(xw.surf, q->begin, q->ctrl[0], q->ctrl[1],
|
||||
q->end, 22, q->line_thickness, q->color);
|
||||
} break;
|
||||
case ZR_COMMAND_RECT_MULTI_COLOR:
|
||||
case ZR_COMMAND_IMAGE:
|
||||
case ZR_COMMAND_ARC:
|
||||
case ZR_COMMAND_ARC_FILLED:
|
||||
default: break;
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue