ltk

Socket-based GUI for X11 (WIP)
git clone git://lumidify.org/ltk.git (fast, but not encrypted)
git clone https://lumidify.org/git/ltk.git (encrypted, but very slow)
Log | Files | Refs | README | LICENSE

commit 7dac53a708dd3625c7aa43f97a79ff0ef94158e3
parent f452a00a4143a913e61a395cf9e4b8728fa0a7a6
Author: lumidify <nobody@lumidify.org>
Date:   Fri, 19 Feb 2021 22:43:45 +0100

Add wrapper for memory allocation

Diffstat:
MMakefile | 4++--
Mbox.c | 15++++++---------
Mbutton.c | 8++++----
Mconfig.mk | 2+-
Mdraw.c | 10+++++-----
Mgrid.c | 37++++++++++++++++++-------------------
Mlabel.c | 8++++----
Mltkd.c | 39+++++++++++++++++----------------------
Amemory.c | 71+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Amemory.h | 34++++++++++++++++++++++++++++++++++
Mscrollbar.c | 7+++----
Dtext_line.c | 143-------------------------------------------------------------------------------
Dtext_line.h | 52----------------------------------------------------
Mtext_pango.c | 11++++++-----
Mtext_stb.c | 34+++++++++++++++-------------------
15 files changed, 186 insertions(+), 289 deletions(-)

diff --git a/Makefile b/Makefile @@ -1,6 +1,6 @@ include config.mk -OBJ += color.o util.o ltkd.o ini.o grid.o box.o scrollbar.o button.o label.o draw.o +OBJ += memory.o color.o util.o ltkd.o ini.o grid.o box.o scrollbar.o button.o label.o draw.o all: ltkd ltkc @@ -16,4 +16,4 @@ ltkc: ltkc.o util.o .PHONY: clean clean: - rm -f $(OBJ) ltkc.o ltkd ltkc ltk.sock *.core + rm -f *.o ltkd ltkc ltk.sock *.core diff --git a/box.c b/box.c @@ -29,6 +29,7 @@ #include <X11/Xlib.h> #include <X11/Xutil.h> +#include "memory.h" #include "color.h" #include "ltk.h" #include "util.h" @@ -88,9 +89,7 @@ ltk_box_draw(ltk_box *box, ltk_rect clip) { static ltk_box * ltk_box_create(ltk_window *window, const char *id, ltk_orientation orient) { - ltk_box *box = malloc(sizeof(ltk_box)); - if (!box) - ltk_fatal("Unable to allocate memory for box.\n"); + ltk_box *box = ltk_malloc(sizeof(ltk_box), "ltk_box_create"); ltk_fill_widget_defaults(&box->widget, id, window, &ltk_box_draw, NULL, &ltk_box_destroy, 0, LTK_BOX); @@ -119,11 +118,11 @@ ltk_box_destroy(ltk_box *box, int shallow) { ptr->destroy(ptr, shallow); } } - free(box->widgets); + ltk_free(box->widgets); ltk_remove_widget(box->widget.window, box->widget.id); - free(box->widget.id); + ltk_free(box->widget.id); box->sc->widget.destroy(box->sc, 0); - free(box); + ltk_free(box); } /* FIXME: Make this function name more consistent */ @@ -224,9 +223,7 @@ ltk_box_add(ltk_window *window, ltk_widget *widget, ltk_box *box, unsigned short } if (box->num_widgets >= box->num_alloc) { size_t new_size = box->num_alloc > 0 ? box->num_alloc * 2 : 4; - ltk_widget **new = realloc(box->widgets, new_size * sizeof(ltk_widget *)); - if (!new) - ltk_fatal_errno("Unable to allocate memory for widgets in box.\n"); + ltk_widget **new = ltk_realloc(box->widgets, new_size * sizeof(ltk_widget *), "ltk_box_add"); box->num_alloc = new_size; box->widgets = new; } diff --git a/button.c b/button.c @@ -30,6 +30,7 @@ #include <X11/Xlib.h> #include <X11/Xutil.h> +#include "memory.h" #include "color.h" #include "ltk.h" #include "util.h" @@ -236,8 +237,7 @@ ltk_button_mouse_release(ltk_button *button, XEvent event) { static ltk_button * ltk_button_create(ltk_window *window, const char *id, const char *text) { char *text_copy; - ltk_button *button = malloc(sizeof(ltk_button)); - if (!button) ltk_fatal_errno("Unable to allocate memory for ltk_button.\n"); + ltk_button *button = ltk_malloc(sizeof(ltk_button), "ltk_button_create"); ltk_fill_widget_defaults(&button->widget, id, window, &ltk_button_draw, &ltk_button_change_state, &ltk_button_destroy, 1, LTK_BUTTON); @@ -268,8 +268,8 @@ ltk_button_destroy(ltk_button *button, int shallow) { } ltk_text_line_destroy(button->tl); ltk_remove_widget(button->widget.window, button->widget.id); - free(button->widget.id); - free(button); + ltk_free(button->widget.id); + ltk_free(button); } /* button <button id> create <text> */ diff --git a/config.mk b/config.mk @@ -1,6 +1,6 @@ VERSION = -999 -CFLAGS = -D_POSIX_C_SOURCE=200809L -g -std=c99 -w -fcommon -Wall -Werror -Wextra `pkg-config --cflags x11 fontconfig` -pedantic +CFLAGS = -DDEBUG -D_POSIX_C_SOURCE=200809L -g -std=c99 -w -fcommon -Wall -Werror -Wextra `pkg-config --cflags x11 fontconfig` -pedantic LDFLAGS = -lm `pkg-config --libs x11 fontconfig` # Comment when enabling pango rendering: OBJ = stb_truetype.o text_stb.o diff --git a/draw.c b/draw.c @@ -30,6 +30,7 @@ #include <X11/Xlib.h> #include <X11/Xutil.h> +#include "memory.h" #include "color.h" #include "ltk.h" #include "util.h" @@ -80,8 +81,7 @@ ltk_draw_draw(ltk_draw *draw) { static ltk_draw * ltk_draw_create(ltk_window *window, const char *id, int w, int h, const char *color) { - ltk_draw *draw = malloc(sizeof(ltk_draw)); - if (!draw) ltk_fatal_errno("Unable to allocate memory for ltk_draw.\n"); + ltk_draw *draw = ltk_malloc(sizeof(ltk_draw), ltk_draw_create); ltk_fill_widget_defaults(&draw->widget, id, window, &ltk_draw_draw, NULL, &ltk_draw_destroy, 1, LTK_DRAW); @@ -90,7 +90,7 @@ ltk_draw_create(ltk_window *window, const char *id, int w, int h, const char *co draw->widget.rect.h = h; draw->pix = XCreatePixmap(window->dpy, window->xwindow, w, h, window->depth); if (!ltk_create_xcolor(window, color, &draw->bg)) { - free(draw); + ltk_free(draw); ltk_fatal_errno("Unable to allocate XColor.\n"); } draw->fg = draw->bg; @@ -130,9 +130,9 @@ ltk_draw_destroy(ltk_draw *draw, int shallow) { return; } ltk_remove_widget(draw->widget.window, draw->widget.id); - free(draw->widget.id); + ltk_free(draw->widget.id); XFreePixmap(draw->widget.window->dpy, draw->pix); - free(draw); + ltk_free(draw); } static void diff --git a/grid.c b/grid.c @@ -36,6 +36,7 @@ #include <X11/Xlib.h> #include <X11/Xutil.h> +#include "memory.h" #include "color.h" #include "ltk.h" #include "util.h" @@ -109,9 +110,7 @@ ltk_grid_draw(ltk_grid *grid, ltk_rect clip) { static ltk_grid * ltk_grid_create(ltk_window *window, const char *id, int rows, int columns) { - ltk_grid *grid = malloc(sizeof(ltk_grid)); - if (!grid) - ltk_fatal("Unable to allocate memory for grid.\n"); + ltk_grid *grid = ltk_malloc(sizeof(ltk_grid), "ltk_grid_create"); ltk_fill_widget_defaults(&grid->widget, id, window, &ltk_grid_draw, NULL, &ltk_grid_destroy, 0, LTK_GRID); @@ -124,14 +123,14 @@ ltk_grid_create(ltk_window *window, const char *id, int rows, int columns) { grid->rows = rows; grid->columns = columns; - grid->widget_grid = malloc(rows * columns * sizeof(ltk_widget)); - grid->row_heights = malloc(rows * sizeof(int)); - grid->column_widths = malloc(rows * sizeof(int)); - grid->row_weights = malloc(rows * sizeof(int)); - grid->column_weights = malloc(columns * sizeof(int)); + grid->widget_grid = ltk_malloc(rows * columns * sizeof(ltk_widget), "ltk_grid_create"); + grid->row_heights = ltk_malloc(rows * sizeof(int), "ltk_grid_create"); + grid->column_widths = ltk_malloc(rows * sizeof(int), "ltk_grid_create"); + grid->row_weights = ltk_malloc(rows * sizeof(int), "ltk_grid_create"); + grid->column_weights = ltk_malloc(columns * sizeof(int), "ltk_grid_create"); /* Positions have one extra for the end */ - grid->row_pos = malloc((rows + 1) * sizeof(int)); - grid->column_pos = malloc((columns + 1) * sizeof(int)); + grid->row_pos = ltk_malloc((rows + 1) * sizeof(int), "ltk_grid_create"); + grid->column_pos = ltk_malloc((columns + 1) * sizeof(int), "ltk_grid_create"); /* FIXME: wow, that's horrible, this should just use memset */ int i; for (i = 0; i < rows; i++) { @@ -172,16 +171,16 @@ ltk_grid_destroy(ltk_grid *grid, int shallow) { } } } - free(grid->widget_grid); - free(grid->row_heights); - free(grid->column_widths); - free(grid->row_weights); - free(grid->column_weights); - free(grid->row_pos); - free(grid->column_pos); + ltk_free(grid->widget_grid); + ltk_free(grid->row_heights); + ltk_free(grid->column_widths); + ltk_free(grid->row_weights); + ltk_free(grid->column_weights); + ltk_free(grid->row_pos); + ltk_free(grid->column_pos); ltk_remove_widget(grid->widget.window, grid->widget.id); - free(grid->widget.id); - free(grid); + ltk_free(grid->widget.id); + ltk_free(grid); } static void diff --git a/label.c b/label.c @@ -30,6 +30,7 @@ #include <X11/Xlib.h> #include <X11/Xutil.h> +#include "memory.h" #include "color.h" #include "ltk.h" #include "util.h" @@ -94,8 +95,7 @@ ltk_label_draw(ltk_label *label, ltk_rect clip) { static ltk_label * ltk_label_create(ltk_window *window, const char *id, const char *text) { char *text_copy; - ltk_label *label = malloc(sizeof(ltk_label)); - if (!label) ltk_fatal_errno("Unable to allocate memory for ltk_label.\n"); + ltk_label *label = ltk_malloc(sizeof(ltk_label), "ltk_label_create"); ltk_fill_widget_defaults(&label->widget, id, window, &ltk_label_draw, NULL, &ltk_label_destroy, 1, LTK_LABEL); @@ -126,8 +126,8 @@ ltk_label_destroy(ltk_label *label, int shallow) { } ltk_text_line_destroy(label->tl); ltk_remove_widget(label->widget.window, label->widget.id); - free(label->widget.id); - free(label); + ltk_free(label->widget.id); + ltk_free(label); } /* label <label id> create <text> */ diff --git a/ltkd.c b/ltkd.c @@ -47,6 +47,7 @@ #include "ini.h" #include "khash.h" +#include "memory.h" #include "color.h" #include "ltk.h" #include "util.h" @@ -257,10 +258,10 @@ ltk_mainloop(ltk_window *window) { ltk_fatal_errno("Unable to queue event.\n"); } } - free(cur->data); + ltk_free(cur->data); last = cur; cur = cur->prev; - free(last); + ltk_free(last); } while (cur); window->first_event = window->last_event = NULL; } @@ -324,9 +325,7 @@ get_sock_path(char *basedir, Window id) { len = strlen(basedir); /* FIXME: MAKE SURE THIS IS ACTUALLY BIG ENOUGH! */ - path = malloc(len + 20); - if (!path) - return NULL; + path = ltk_malloc(len + 20, "get_sock_path"); /* FIXME: also check for less than 0 */ if (snprintf(path, len + 20, "%s/%d.sock", basedir, id) >= len + 20) ltk_fatal("Tell lumidify to fix his code.\n"); @@ -345,10 +344,10 @@ open_log(char *dir) { return NULL; f = fopen(path, "a"); if (!f) { - free(path); + ltk_free(path); return NULL; } - free(path); + ltk_free(path); return f; } @@ -358,23 +357,23 @@ ltk_cleanup(void) { if (listenfd >= 0) close(listenfd); if (ltk_dir) - free(ltk_dir); + ltk_free(ltk_dir); if (ltk_logfile) fclose(ltk_logfile); if (sock_path) { unlink(sock_path); - free(sock_path); + ltk_free(sock_path); } for (int i = 0; i < MAX_SOCK_CONNS; i++) { if (sockets[i].fd >= 0) close(sockets[i].fd); if (sockets[i].read) - free(sockets[i].read); + ltk_free(sockets[i].read); if (sockets[i].to_write) - free(sockets[i].to_write); + ltk_free(sockets[i].to_write); if (sockets[i].tokens.tokens) - free(sockets[i].tokens.tokens); + ltk_free(sockets[i].tokens.tokens); } if (widget_hash) @@ -515,13 +514,11 @@ ltk_create_xcolor(ltk_window *window, const char *hex, XColor *col) { void ltk_queue_event(ltk_window *window, ltk_event_type type, const char *id, const char *data) { /* FIXME: make it nicer and safer */ - struct ltk_event_queue *new = malloc(sizeof(struct ltk_event_queue)); - if (!new) ltk_fatal_errno("Unable to queue event.\n"); + struct ltk_event_queue *new = ltk_malloc(sizeof(struct ltk_event_queue), "ltk_queue_event"); new->event_type = type; int id_len = strlen(id); int data_len = strlen(data); - new->data = malloc(id_len + data_len + 3); - if (!new->data) ltk_fatal_errno("Unable to queue event.\n"); + new->data = ltk_malloc(id_len + data_len + 3, "ltk_queue_event"); strcpy(new->data, id); new->data[id_len] = ' '; strcpy(new->data + id_len + 1, data); @@ -588,9 +585,7 @@ ltk_create_window(const char *title, int x, int y, unsigned int w, unsigned int char *theme_path; XWindowAttributes attrs; - ltk_window *window = malloc(sizeof(ltk_window)); - if (!window) - ltk_fatal_errno("Not enough memory left for window!\n"); + ltk_window *window = ltk_malloc(sizeof(ltk_window), "ltk_create_window"); window->dpy = XOpenDisplay(NULL); window->screen = DefaultScreen(window->dpy); @@ -665,8 +660,8 @@ ltk_destroy_window(ltk_window *window) { /* FIXME: This doesn't work because it can sometimes be a readonly string from ltk_window_setup_theme_defaults! */ if (window->theme.font) - free(window->theme.font); - free(window); + ltk_free(window->theme.font); + ltk_free(window); } void @@ -962,7 +957,7 @@ push_token(struct token_list *tl, char *token) { if (tl->num_tokens >= tl->num_alloc) { new_size = (tl->num_alloc * 2) > (tl->num_tokens + 1) ? (tl->num_alloc * 2) : (tl->num_tokens + 1); - char **new = realloc(tl->tokens, new_size * sizeof(char *)); + char **new = ltk_realloc(tl->tokens, new_size * sizeof(char *), "push_token"); if (!new) return -1; tl->tokens = new; tl->num_alloc = new_size; diff --git a/memory.c b/memory.c @@ -0,0 +1,71 @@ +/* + * This file is part of the Lumidify ToolKit (LTK) + * Copyright (c) 2021 lumidify <nobody@lumidify.org> + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#include <stdio.h> +#include <stdlib.h> +#include <X11/Xlib.h> +#include <X11/Xutil.h> +#include <stdarg.h> +#include "color.h" +#include "ltk.h" + +void * +ltk_malloc(size_t size, const char *caller) { + void *ptr = malloc(size); + if (!ptr) + ltk_fatal("%s: out of memory.\n", caller); + #ifdef DEBUG + fprintf(stderr, "DEBUG: malloc: address %p, %zu bytes.\n", ptr, size); + #endif + return ptr; +} + +void * +ltk_calloc(size_t nmemb, size_t size, const char *caller) { + void *ptr = calloc(nmemb, size); + if (!ptr) + ltk_fatal("%s: out of memory.\n", caller); + #ifdef DEBUG + fprintf(stderr, "DEBUG: calloc: address %p, %zu bytes.\n", ptr, size); + #endif + return ptr; +} + +void * +ltk_realloc(void *ptr, size_t size, const char *caller) { + void *new_ptr = realloc(ptr, size); + if (!new_ptr) + ltk_fatal("%s: out of memory.\n", caller); + #ifdef DEBUG + fprintf(stderr, "DEBUG: realloc: old %p, new %p, %zu bytes.\n", ptr, new_ptr, size); + #endif + return new_ptr; +} + +void +ltk_free(void *ptr) { + #ifdef DEBUG + fprintf(stderr, "DEBUG: free: address %p\n", ptr); + #endif + free(ptr); +} diff --git a/memory.h b/memory.h @@ -0,0 +1,34 @@ +/* + * This file is part of the Lumidify ToolKit (LTK) + * Copyright (c) 2021 lumidify <nobody@lumidify.org> + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#ifndef _LTK_MEMORY_H_ +#define _LTK_MEMORY_H_ + +/* FIXME: Move ltk_warn, etc. to util.* */ + +void *ltk_malloc(size_t size, const char *caller); +void *ltk_calloc(size_t nmemb, size_t size, const char *caller); +void *ltk_realloc(void *ptr, size_t size, const char *caller); +void ltk_free(void *ptr); + +#endif /* _LTK_MEMORY_H_ */ diff --git a/scrollbar.c b/scrollbar.c @@ -30,6 +30,7 @@ #include <X11/Xlib.h> #include <X11/Xutil.h> +#include "memory.h" #include "color.h" #include "ltk.h" #include "util.h" @@ -221,9 +222,7 @@ ltk_scrollbar_motion_notify(ltk_scrollbar *sc, XEvent event) { ltk_scrollbar * ltk_scrollbar_create(ltk_window *window, ltk_orientation orient, void (*callback)(void *), void *data) { - ltk_scrollbar *sc = malloc(sizeof(ltk_scrollbar)); - if (!sc) - ltk_fatal_errno("Unable to allocate memory for scrollbar.\n"); + ltk_scrollbar *sc = ltk_malloc(sizeof(ltk_scrollbar), "ltk_scrollbar_create"); ltk_fill_widget_defaults(sc, NULL, window, &ltk_scrollbar_draw, NULL, &ltk_scrollbar_destroy, 1, LTK_UNKNOWN); sc->last_mouse_x = sc->last_mouse_y = 0; @@ -245,5 +244,5 @@ ltk_scrollbar_create(ltk_window *window, ltk_orientation orient, void (*callback static void ltk_scrollbar_destroy(ltk_scrollbar *scrollbar, int shallow) { - free(scrollbar); + ltk_free(scrollbar); } diff --git a/text_line.c b/text_line.c @@ -1,143 +0,0 @@ -/* - * This file is part of the Lumidify ToolKit (LTK) - * Copyright (c) 2020 lumidify <nobody@lumidify.org> - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#include <stdio.h> -#include <stdlib.h> -#include <stdint.h> -#include <X11/Xlib.h> -#include <X11/Xutil.h> -#include "text_common.h" -#include "text_line.h" -#include "util.h" - -void ltk_init_text(const char *default_font, Display *dpy, int screen, Colormap cm); -void ltk_cleanup_text(void); - -LtkTextLine *ltk_text_line_create(Window window, uint16_t font_size, char *text, int width); -void ltk_text_line_render(LtkTextLine *tl, LtkColor *bg, LtkColor *fg); -void ltk_text_line_draw(LtkTextLine *tl, GC gc, int x, int y, ltk_rect clip); -void ltk_text_line_set_width(LtkTextLine *tl, int width); -void ltk_text_line_get_size(LtkTextLine *tl, int *w, int *h); -void ltk_text_line_destroy(LtkTextLine *tl); - -static void ltk_text_line_create_glyphs(struct ltk_text_line *tl); -static void ltk_text_line_draw_glyph(ltk_glyph *glyph, int xoff, int yoff, - XImage *img, XColor fg); -static XImage *ltk_create_ximage(Display *dpy, int w, int h, int depth, - XColor bg); - -static XImage * -ltk_create_ximage(Display *dpy, int w, int h, int depth, XColor bg) { - XImage *img = XCreateImage(dpy, CopyFromParent, depth, ZPixmap, 0, NULL, w, h, 32, 0); - img->data = calloc(img->bytes_per_line, img->height); - XInitImage(img); - - int b; - for (int i = 0; i < h; i++) { - b = img->bytes_per_line * i; - for (int j = 0; j < w; j++) { - img->data[b++] = bg.blue / 257; - img->data[b++] = bg.green / 257; - img->data[b++] = bg.red / 257; - b++; - } - } - - return img; -} - -/* based on http://codemadness.org/git/dwm-font/file/drw.c.html#l315 */ -static void -ltk_text_line_draw_glyph(ltk_glyph *glyph, int xoff, int yoff, XImage *img, XColor fg) { - int x = glyph->x + xoff; - int y = glyph->y + yoff; - double a; - int b; - for (int i = 0; i < glyph->info->h; i++) { - for (int j = 0; j < glyph->info->w; j++) { - if (y + i >= img->height || x + j >= img->width || - y + i < 0 || x + i < 0) - continue; - b = (y + i) * img->bytes_per_line + (x + j) * 4; - a = glyph->info->alphamap[i * glyph->info->w + j] / 255.0; - img->data[b] = (fg.blue * a + (1 - a) * (uint16_t)img->data[b] * 257) / 257; - img->data[b + 1] = (fg.green * a + (1 - a) * (uint16_t)img->data[b + 1] * 257) / 257; - img->data[b + 2] = (fg.red * a + (1 - a) * (uint16_t)img->data[b + 2] * 257) / 257; - } - } -} - -XImage * -ltk_text_line_render( - struct ltk_text_line *tl, - Display *dpy, - Window window, - GC gc, - Colormap colormap, - XColor fg, - XColor bg) -{ - ltk_glyph *glyph; - - XWindowAttributes attrs; - XGetWindowAttributes(dpy, window, &attrs); - int depth = attrs.depth; - /* FIXME: pass old image; if it has same dimensions, just clear it */ - XImage *img = ltk_create_ximage(dpy, tl->w, tl->h, depth, bg); - for (int i = 0; i < tl->glyph_len; i++) { - ltk_text_line_draw_glyph(&tl->glyphs[i], -tl->x_min, -tl->y_min, img, fg); - } - return img; -} - -static void -ltk_text_line_create_glyphs(LtkTextLine *tl) { - int x_min, x_max, y_min, y_max; - ltk_text_to_glyphs(tl->glyphs, tl->glyph_len, tl->text, tl->font_size, - &x_min, &y_min, &x_max, &y_max); - /* for drawing the glyphs at the right position on the image */ - tl->x_min = x_min; - tl->y_min = y_min; - tl->w = x_max - x_min; - tl->h = y_max - y_min; -} - -LtkTextLine * -ltk_text_line_create(uint16_t font_size, char *text, int width) { - LtkTextLine *line = malloc(sizeof(LtkTextLine)); - if (!line) ltk_err("ltk_text_line_create (basic)"); - line->text = text; - line->glyph_len = u8_strlen(text); - line->glyphs = malloc(line->glyph_len * sizeof(ltk_glyph)); - line->font_size = font_size; - ltk_text_line_create_glyphs(line); - return line; -} - -void -ltk_text_line_destroy(LtkTextLine *tl) { - free(tl->text); - /* FIXME: Reference count glyph infos */ - free(tl->glyphs); - free(tl); -} diff --git a/text_line.h b/text_line.h @@ -1,52 +0,0 @@ -/* - * This file is part of the Lumidify ToolKit (LTK) - * Copyright (c) 2020 lumidify <nobody@lumidify.org> - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#ifndef _TEXT_LINE_H_ -#define _TEXT_LINE_H_ - -/* -Requires the following includes: -<X11/Xlib.h>, <X11/Xutil.h>, <stdint.h> -*/ - -typedef struct { - char *text; - ltk_glyph *glyphs; - size_t glyph_len; - uint16_t font_size; - int w; - int h; - int x_min; - int y_min; -} LtkTextLine; - -void ltk_init_text(const char *default_font, Display *dpy, int screen, Colormap cm); -void ltk_cleanup_text(void); -LtkTextLine *ltk_text_line_create(Window window, uint16_t font_size, char *text, int width); -void ltk_text_line_render(LtkTextLine *tl, LtkColor *bg, LtkColor *fg); -void ltk_text_line_draw(LtkTextLine *tl, GC gc, int x, int y); -void ltk_text_line_set_width(LtkTextLine *tl, int width); -void ltk_text_line_get_size(LtkTextLine *tl, int *w, int *h); -void ltk_text_line_destroy(LtkTextLine *tl); - -#endif /* _TEXT_LINE_H_ */ diff --git a/text_pango.c b/text_pango.c @@ -10,6 +10,7 @@ #include <pango/pangoxft.h> +#include "memory.h" #include "color.h" #include "ltk.h" #include "util.h" @@ -49,7 +50,8 @@ ltk_init_text(const char *default_font, Display *dpy, int screen, Colormap cm) { void ltk_cleanup_text(void) { - if (tm.default_font) free(tm.default_font); + /* FIXME: strdup, etc. wrapper */ + if (tm.default_font) ltk_free(tm.default_font); /* FIXME: destroy fontmap and context */ } @@ -62,8 +64,7 @@ LtkTextLine * ltk_text_line_create(Window window, uint16_t font_size, char *text, int width) { if (!tm.context) ltk_err("ltk_text_line_create (pango): text not initialized yet"); - LtkTextLine *line = malloc(sizeof(LtkTextLine)); - if (!line) ltk_err("ltk_text_line_create (pango)"); + LtkTextLine *line = ltk_malloc(sizeof(LtkTextLine), "ltk_text_line_create"); line->text = text; line->font_size = font_size; line->layout = pango_layout_new(tm.context); @@ -115,6 +116,6 @@ ltk_text_line_destroy(LtkTextLine *tl) { g_object_unref(tl->layout); XftDrawDestroy(tl->draw); XFreePixmap(tm.dpy, tl->pixmap); - free(tl->text); - free(tl); + ltk_free(tl->text); + ltk_free(tl); } diff --git a/text_stb.c b/text_stb.c @@ -35,6 +35,7 @@ #include "khash.h" #include "stb_truetype.h" /* http://nothings.org/stb/stb_truetype.h */ +#include "memory.h" #include "color.h" #include "ltk.h" #include "util.h" @@ -200,8 +201,7 @@ void ltk_init_text(const char *default_font, Display *dpy, int screen, Colormap cm) { tm.fonts_bufsize = 1; tm.glyph_cache = kh_init(glyphcache); - tm.fonts = malloc(sizeof(LtkFont *)); - if (!tm.fonts) ltk_err("ltk_init_text"); + tm.fonts = ltk_malloc(sizeof(LtkFont *), "ltk_init_text"); ltk_load_default_font(default_font); tm.dpy = dpy; tm.screen = screen; @@ -224,8 +224,7 @@ ltk_cleanup_text(void) { static LtkGlyphInfo * ltk_create_glyph_info(LtkFont *font, int id, float scale) { - LtkGlyphInfo *glyph = malloc(sizeof(LtkGlyphInfo)); - if (!glyph) ltk_err("ltk_create_glyph_info"); + LtkGlyphInfo *glyph = ltk_malloc(sizeof(LtkGlyphInfo), "ltk_create_glyph_info"); glyph->id = id; glyph->refs = 0; @@ -239,8 +238,8 @@ ltk_create_glyph_info(LtkFont *font, int id, float scale) { static void ltk_destroy_glyph_info(LtkGlyphInfo *gi) { - free(gi->alphamap); - free(gi); + ltk_free(gi->alphamap); + ltk_free(gi); } static LtkGlyphInfo * @@ -321,8 +320,7 @@ ltk_load_default_font(char *name) { static LtkFont * ltk_create_font(char *path, uint16_t id, int index) { unsigned long len; - LtkFont *font = malloc(sizeof(LtkFont)); - if (!font) ltk_err("ltk_create_font (stb)"); + LtkFont *font = ltk_malloc(sizeof(LtkFont), "ltk_create_font"); char *contents = ltk_read_file(path, &len); if (!contents) ltk_fatal_errno("Unable to read font file %s\n", path); @@ -341,16 +339,15 @@ ltk_create_font(char *path, uint16_t id, int index) { static void ltk_destroy_font(LtkFont *font) { - free(font->info.data); - free(font); + ltk_free(font->info.data); + ltk_free(font); } static LtkFont * ltk_load_font(char *path, int index) { LtkFont *font = ltk_create_font(path, tm.font_id_cur++, index); if (tm.num_fonts == tm.fonts_bufsize) { - LtkFont *new = realloc(tm.fonts, tm.fonts_bufsize * 2 * sizeof(LtkFont *)); - if (!new) ltk_err("ltk_load_font"); + LtkFont *new = ltk_realloc(tm.fonts, tm.fonts_bufsize * 2 * sizeof(LtkFont *), "ltk_load_font"); tm.fonts = new; tm.fonts_bufsize *= 2; } @@ -474,7 +471,7 @@ ltk_unref_glyphs(ltk_glyph *glyphs, int num_glyphs) { static XImage * ltk_create_ximage(int w, int h, int depth, XColor bg) { XImage *img = XCreateImage(tm.dpy, CopyFromParent, depth, ZPixmap, 0, NULL, w, h, 32, 0); - img->data = calloc(img->bytes_per_line, img->height); + img->data = ltk_calloc(img->bytes_per_line, img->height, "ltk_create_ximage"); XInitImage(img); int b; @@ -572,13 +569,12 @@ ltk_text_line_create_glyphs(LtkTextLine *tl) { LtkTextLine * ltk_text_line_create(Window window, uint16_t font_size, char *text, int width) { - LtkTextLine *line = malloc(sizeof(LtkTextLine)); - if (!line) ltk_err("ltk_text_line_create (basic)"); + LtkTextLine *line = ltk_malloc(sizeof(LtkTextLine), "ltk_text_line_create"); line->window = window; line->img = NULL; line->text = text; line->glyph_len = u8_strlen(text); - line->glyphs = malloc(line->glyph_len * sizeof(LtkGlyph)); + line->glyphs = ltk_malloc(line->glyph_len * sizeof(LtkGlyph), "ltk_text_line_create"); line->font_size = font_size; ltk_text_line_create_glyphs(line); return line; @@ -586,8 +582,8 @@ ltk_text_line_create(Window window, uint16_t font_size, char *text, int width) { void ltk_text_line_destroy(LtkTextLine *tl) { - free(tl->text); + ltk_free(tl->text); /* FIXME: Reference count glyph infos */ - free(tl->glyphs); - free(tl); + ltk_free(tl->glyphs); + ltk_free(tl); }