commit d1f0903f23c0887590329483d8993cbefb1b6189
parent 00cefe189580f8332951122af1f6d6230d9652c3
Author: lumidify <nobody@lumidify.org>
Date: Thu, 5 May 2022 13:14:22 +0200
Slightly improve graphics and text interface
Diffstat:
14 files changed, 311 insertions(+), 311 deletions(-)
diff --git a/Makefile b/Makefile
@@ -18,7 +18,8 @@ LDFLAGS += -lm `pkg-config --libs x11 fontconfig xext`
# Note: this macro magic for debugging and pango rendering seems ugly; it should probably be changed
# debug
-DEV_1 = -g -Wall -Werror -Wextra -pedantic
+DEV_1 = -g -Wall -Wextra -pedantic
+#-Werror
# stb rendering
EXTRA_OBJ_0 = src/stb_truetype.o src/text_stb.o
diff --git a/src/box.h b/src/box.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2021 lumidify <nobody@lumidify.org>
+ * Copyright (c) 2021, 2022 lumidify <nobody@lumidify.org>
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
@@ -22,6 +22,8 @@
typedef struct {
ltk_widget widget;
ltk_scrollbar *sc;
+ ltk_widget *pressed_widget;
+ ltk_widget *active_widget;
ltk_widget **widgets;
size_t num_alloc;
size_t num_widgets;
diff --git a/src/button.c b/src/button.c
@@ -37,7 +37,7 @@
static void ltk_button_draw(ltk_widget *self, ltk_rect clip);
static int ltk_button_mouse_release(ltk_widget *self, XEvent event);
static ltk_button *ltk_button_create(ltk_window *window,
- const char *id, const char *text);
+ const char *id, char *text);
static void ltk_button_destroy(ltk_widget *self, int shallow);
static void ltk_button_change_state(ltk_widget *self);
static void ltk_button_redraw_surface(ltk_button *button, ltk_surface *s);
@@ -142,12 +142,11 @@ ltk_button_draw(ltk_widget *self, ltk_rect clip) {
ltk_surface *s;
if (!ltk_surface_cache_get_surface(self->surface_key, &s) || self->dirty)
ltk_button_redraw_surface(button, s);
- ltk_surface_copy_to_window(s, self->window, ltk_rect_relative(rect, clip_final), clip_final.x, clip_final.y);
+ ltk_surface_copy(s, self->window->surface, ltk_rect_relative(rect, clip_final), clip_final.x, clip_final.y);
}
static void
ltk_button_redraw_surface(ltk_button *button, ltk_surface *s) {
- ltk_window *window = button->widget.window;
ltk_rect rect = button->widget.rect;
int bw = theme.border_width;
ltk_color *border = NULL, *fill = NULL;
@@ -181,33 +180,12 @@ ltk_button_redraw_surface(ltk_button *button, ltk_surface *s) {
ltk_text_line_get_size(button->tl, &text_w, &text_h);
int text_x = (rect.w - text_w) / 2;
int text_y = (rect.h - text_h) / 2;
- /* FIXME: Remove clipping rect from text line - this is just used here as a dummy
- because it is completely ignored */
- ltk_text_line_draw(button->tl, s, window->gc, text_x, text_y, rect);
+ ltk_text_line_draw(button->tl, s, &theme.text_color, text_x, text_y);
button->widget.dirty = 0;
}
static void
ltk_button_change_state(ltk_widget *self) {
- ltk_button *button = (ltk_button *)self;
- ltk_color *fill = NULL;
- switch (button->widget.state) {
- case LTK_NORMAL:
- fill = &theme.fill;
- break;
- case LTK_PRESSED:
- fill = &theme.fill_pressed;
- break;
- case LTK_ACTIVE:
- fill = &theme.fill_active;
- break;
- case LTK_DISABLED:
- fill = &theme.fill_disabled;
- break;
- default:
- ltk_fatal("No style found for button!\n");
- }
- ltk_text_line_change_colors(button->tl, &theme.text_color, fill);
self->dirty = 1;
}
@@ -220,20 +198,17 @@ ltk_button_mouse_release(ltk_widget *self, XEvent event) {
}
static ltk_button *
-ltk_button_create(ltk_window *window, const char *id, const char *text) {
- char *text_copy;
+ltk_button_create(ltk_window *window, const char *id, char *text) {
ltk_button *button = ltk_malloc(sizeof(ltk_button));
uint16_t font_size = window->theme.font_size;
- text_copy = ltk_strdup(text);
- button->tl = ltk_text_line_create(window->xwindow, font_size, text_copy, -1, &theme.text_color, &theme.fill);
+ button->tl = ltk_text_line_create(window->text_context, font_size, text, 0, -1);
int text_w, text_h;
ltk_text_line_get_size(button->tl, &text_w, &text_h);
button->widget.ideal_w = text_w + theme.border_width * 2 + theme.pad * 2;
button->widget.ideal_h = text_h + theme.border_width * 2 + theme.pad * 2;
ltk_fill_widget_defaults(&button->widget, id, window, &vtable, button->widget.ideal_w, button->widget.ideal_h);
- /* render text */
- ltk_button_change_state((ltk_widget *)button);
+ button->widget.dirty = 1;
return button;
}
diff --git a/src/color.h b/src/color.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2021 lumidify <nobody@lumidify.org>
+ * Copyright (c) 2021, 2022 lumidify <nobody@lumidify.org>
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
@@ -17,13 +17,15 @@
#ifndef _LTK_COLOR_H_
#define _LTK_COLOR_H_
-#if USE_PANGO == 1
+#include "compat.h"
+
+#if USE_XFT == 1
#include <X11/Xft/Xft.h>
#endif
typedef struct {
XColor xcolor;
- #if USE_PANGO == 1
+ #if USE_XFT == 1
XftColor xftcolor;
#endif
} ltk_color;
diff --git a/src/compat.h b/src/compat.h
@@ -0,0 +1,9 @@
+#ifdef _LTK_COMPAT_H_
+#define _LTK_COMPAT_H_
+
+#if USE_PANGO == 1
+#undef USE_XFT
+#define USE_XFT 1
+#endif
+
+#endif
diff --git a/src/graphics.h b/src/graphics.h
@@ -17,30 +17,31 @@
#ifndef _LTK_GRAPHICS_H_
#define _LTK_GRAPHICS_H_
+/* FIXME: make this global and use it elsewhere */
+#define USE_XLIB_GRAPHICS 1
+
/* FIXME: Is it faster to take ltk_color* or ltk_color? */
#include <X11/Xft/Xft.h>
#include "rect.h"
#include "color.h"
#include "ltk.h"
+#include "compat.h"
-typedef struct ltk_surface ltk_surface;
+/* typedef struct ltk_surface ltk_surface; */
/* FIXME: graphics context */
ltk_surface *ltk_surface_create(ltk_window *window, int w, int h);
void ltk_surface_destroy(ltk_surface *s);
-void ltk_surface_resize(ltk_surface *s, int w, int h);
-void ltk_surface_copy(ltk_surface *src, ltk_surface *dst, ltk_rect src_rect, int dst_x, int dst_y);
-void ltk_surface_copy_to_window(ltk_surface *src, ltk_window *dst, ltk_rect src_rect, int dst_x, int dst_y);
+/* returns 0 if successful, 1 if not resizable */
+int ltk_surface_resize(ltk_surface *s, int w, int h);
+/* FIXME: kind of hacky */
+void ltk_surface_update_size(ltk_surface *s, int w, int h);
+ltk_surface *ltk_surface_from_window(ltk_window *window);
void ltk_surface_get_size(ltk_surface *s, int *w, int *h);
-
-/* The ltk_surface* and ltk_window* functions do the same things, but a window cannot
- be wrapped in an ltk_surface since the resize function wouldn't make sense there */
-/* FIXME: avoid this ugliness */
+void ltk_surface_copy(ltk_surface *src, ltk_surface *dst, ltk_rect src_rect, int dst_x, int dst_y);
void ltk_surface_draw_rect(ltk_surface *s, ltk_color *c, ltk_rect rect, int line_width);
void ltk_surface_fill_rect(ltk_surface *s, ltk_color *c, ltk_rect rect);
-void ltk_window_draw_rect(ltk_window *window, ltk_color *c, ltk_rect rect, int line_width);
-void ltk_window_fill_rect(ltk_window *window, ltk_color *c, ltk_rect rect);
/* TODO */
/*
@@ -50,10 +51,12 @@ void ltk_surface_draw_circle(ltk_surface *s, ltk_color *c, int xc, int yc, int r
void ltk_surface_fill_circle(ltk_surface *s, ltk_color *c, int xc, int yc, int r);
*/
-#if USE_PANGO == 1
+/* FIXME: only generate draw if needed */
+#if USE_XFT == 1
XftDraw *ltk_surface_get_xft_draw(ltk_surface *s);
#endif
-/* FIXME: only expose this when needed */
-Pixmap ltk_surface_get_pixmap(ltk_surface *s);
+#if USE_XLIB_GRAPHICS == 1
+Drawable ltk_surface_get_drawable(ltk_surface *s);
+#endif
#endif /* _LTK_GRAPHICS_H_ */
diff --git a/src/graphics_xlib.c b/src/graphics_xlib.c
@@ -23,14 +23,16 @@
#include "widget.h"
#include "ltk.h"
#include "memory.h"
+#include "compat.h"
struct ltk_surface {
- int w, h;
- ltk_window *window;
- Pixmap p;
- #if USE_PANGO == 1
- XftDraw *xftdraw;
- #endif
+ int w, h;
+ ltk_window *window;
+ Drawable d;
+ #if USE_XFT == 1
+ XftDraw *xftdraw;
+ #endif
+ char resizable;
};
ltk_surface *
@@ -39,31 +41,56 @@ ltk_surface_create(ltk_window *window, int w, int h) {
s->w = w;
s->h = h;
s->window = window;
- s->p = XCreatePixmap(window->dpy, window->xwindow, w, h, window->depth);
- #if USE_PANGO == 1
- s->xftdraw = XftDrawCreate(window->dpy, s->p, window->vis, window->cm);
+ s->d = XCreatePixmap(window->dpy, window->xwindow, w, h, window->depth);
+ #if USE_XFT == 1
+ s->xftdraw = XftDrawCreate(window->dpy, s->d, window->vis, window->cm);
#endif
+ s->resizable = 1;
+ return s;
+}
+
+ltk_surface *
+ltk_surface_from_window(ltk_window *window) {
+ ltk_surface *s = ltk_malloc(sizeof(ltk_surface));
+ s->w = window->rect.w;
+ s->h = window->rect.h;
+ s->window = window;
+ s->d = window->drawable;
+ #if USE_XFT == 1
+ s->xftdraw = XftDrawCreate(window->dpy, s->d, window->vis, window->cm);
+ #endif
+ s->resizable = 0;
return s;
}
void
ltk_surface_destroy(ltk_surface *s) {
- #if USE_PANGO == 1
+ #if USE_XFT == 1
XftDrawDestroy(s->xftdraw);
#endif
- XFreePixmap(s->window->dpy, s->p);
+ if (s->resizable)
+ XFreePixmap(s->window->dpy, (Pixmap)s->d);
ltk_free(s);
}
void
+ltk_surface_update_size(ltk_surface *s, int w, int h) {
+ s->w = w;
+ s->h = h;
+}
+
+int
ltk_surface_resize(ltk_surface *s, int w, int h) {
+ if (!s->resizable)
+ return 1;
s->w = w;
s->h = h;
- XFreePixmap(s->window->dpy, s->p);
- s->p = XCreatePixmap(s->window->dpy, s->window->xwindow, w, h, s->window->depth);
- #if USE_PANGO == 1
- XftDrawChange(s->xftdraw, s->p);
+ XFreePixmap(s->window->dpy, (Pixmap)s->d);
+ s->d = XCreatePixmap(s->window->dpy, s->window->xwindow, w, h, s->window->depth);
+ #if USE_XFT == 1
+ XftDrawChange(s->xftdraw, s->d);
#endif
+ return 0;
}
void
@@ -76,13 +103,13 @@ void
ltk_surface_draw_rect(ltk_surface *s, ltk_color *c, ltk_rect rect, int line_width) {
XSetForeground(s->window->dpy, s->window->gc, c->xcolor.pixel);
XSetLineAttributes(s->window->dpy, s->window->gc, line_width, LineSolid, CapButt, JoinMiter);
- XDrawRectangle(s->window->dpy, s->p, s->window->gc, rect.x, rect.y, rect.w, rect.h);
+ XDrawRectangle(s->window->dpy, s->d, s->window->gc, rect.x, rect.y, rect.w, rect.h);
}
void
ltk_surface_fill_rect(ltk_surface *s, ltk_color *c, ltk_rect rect) {
XSetForeground(s->window->dpy, s->window->gc, c->xcolor.pixel);
- XFillRectangle(s->window->dpy, s->p, s->window->gc, rect.x, rect.y, rect.w, rect.h);
+ XFillRectangle(s->window->dpy, s->d, s->window->gc, rect.x, rect.y, rect.w, rect.h);
}
void
@@ -98,6 +125,14 @@ ltk_window_fill_rect(ltk_window *window, ltk_color *c, ltk_rect rect) {
XFillRectangle(window->dpy, window->drawable, window->gc, rect.x, rect.y, rect.w, rect.h);
}
+void
+ltk_surface_copy(ltk_surface *src, ltk_surface *dst, ltk_rect src_rect, int dst_x, int dst_y) {
+ XCopyArea(
+ src->window->dpy, src->d, dst->d, src->window->gc,
+ src_rect.x, src_rect.y, src_rect.w, src_rect.h, dst_x, dst_y
+ );
+}
+
/* TODO */
/*
void
@@ -117,30 +152,16 @@ ltk_surface_fill_circle(ltk_surface *s, ltk_color *c, int xc, int yc, int r) {
}
*/
-void
-ltk_surface_copy(ltk_surface *src, ltk_surface *dst, ltk_rect src_rect, int dst_x, int dst_y) {
- XCopyArea(
- src->window->dpy, src->p, dst->p, src->window->gc,
- src_rect.x, src_rect.y, src_rect.w, src_rect.h, dst_x, dst_y
- );
-}
-
-void
-ltk_surface_copy_to_window(ltk_surface *src, ltk_window *dst, ltk_rect src_rect, int dst_x, int dst_y) {
- XCopyArea(
- src->window->dpy, src->p, dst->drawable, src->window->gc,
- src_rect.x, src_rect.y, src_rect.w, src_rect.h, dst_x, dst_y
- );
-}
-
-#if USE_PANGO == 1
+#if USE_XFT == 1
XftDraw *
ltk_surface_get_xft_draw(ltk_surface *s) {
return s->xftdraw;
}
#endif
-Pixmap
-ltk_surface_get_pixmap(ltk_surface *s) {
- return s->p;
+#if USE_XLIB_GRAPHICS == 1
+Drawable
+ltk_surface_get_drawable(ltk_surface *s) {
+ return s->d;
}
+#endif
diff --git a/src/label.c b/src/label.c
@@ -36,7 +36,7 @@
static void ltk_label_draw(ltk_widget *self, ltk_rect clip);
static ltk_label *ltk_label_create(ltk_window *window,
- const char *id, const char *text);
+ const char *id, char *text);
static void ltk_label_destroy(ltk_widget *self, int shallow);
static void ltk_label_redraw_surface(ltk_label *label, ltk_surface *s);
@@ -86,7 +86,7 @@ ltk_label_draw(ltk_widget *self, ltk_rect clip) {
ltk_surface *s;
if (!ltk_surface_cache_get_surface(self->surface_key, &s) || self->dirty)
ltk_label_redraw_surface(label, s);
- ltk_surface_copy_to_window(s, self->window, ltk_rect_relative(rect, clip_final), clip_final.x, clip_final.y);
+ ltk_surface_copy(s, self->window->surface, ltk_rect_relative(rect, clip_final), clip_final.x, clip_final.y);
}
static void
@@ -100,17 +100,15 @@ ltk_label_redraw_surface(ltk_label *label, ltk_surface *s) {
ltk_text_line_get_size(label->tl, &text_w, &text_h);
int text_x = (r.w - text_w) / 2;
int text_y = (r.h - text_h) / 2;
- ltk_text_line_draw(label->tl, s, label->widget.window->gc, text_x, text_y, r);
+ ltk_text_line_draw(label->tl, s, &theme.text_color, text_x, text_y);
}
static ltk_label *
-ltk_label_create(ltk_window *window, const char *id, const char *text) {
- char *text_copy;
+ltk_label_create(ltk_window *window, const char *id, char *text) {
ltk_label *label = ltk_malloc(sizeof(ltk_label));
uint16_t font_size = window->theme.font_size;
- text_copy = ltk_strdup(text);
- label->tl = ltk_text_line_create(window->xwindow, font_size, text_copy, -1, &theme.text_color, &theme.bg_color);
+ label->tl = ltk_text_line_create(window->text_context, font_size, text, 0, -1);
int text_w, text_h;
ltk_text_line_get_size(label->tl, &text_w, &text_h);
label->widget.ideal_w = text_w + theme.pad * 2;
diff --git a/src/ltk.h b/src/ltk.h
@@ -56,10 +56,16 @@ struct ltk_event_queue {
though, so it's just going to stay that way.
*/
+/* FIXME: fix this ugliness; remove circular dependencies */
+typedef struct ltk_text_context ltk_text_context;
+typedef struct ltk_surface ltk_surface;
+
typedef struct ltk_window {
Display *dpy;
Visual *vis;
ltk_surface_cache *surface_cache;
+ ltk_text_context *text_context;
+ ltk_surface *surface;
Colormap cm;
GC gc;
int screen;
diff --git a/src/ltkd.c b/src/ltkd.c
@@ -506,6 +506,7 @@ ltk_window_other_event(ltk_window *window, XEvent event) {
window->rect.w = w;
window->rect.h = h;
ltk_window_invalidate_rect(window, window->rect);
+ ltk_surface_update_size(window->surface, w, h);
if (ptr) {
ptr->rect.w = w;
ptr->rect.h = h;
@@ -616,10 +617,7 @@ ltk_create_window(const char *title, int x, int y, unsigned int w, unsigned int
window->surface_cache = ltk_surface_cache_create(window);
- ltk_init_text(window->theme.font, window->dpy, window->screen, window->cm);
-
window->other_event = <k_window_other_event;
-
window->first_event = window->last_event = NULL;
window->rect.w = 0;
@@ -630,6 +628,9 @@ ltk_create_window(const char *title, int x, int y, unsigned int w, unsigned int
window->dirty_rect.h = 0;
window->dirty_rect.x = 0;
window->dirty_rect.y = 0;
+ window->surface = ltk_surface_from_window(window);
+
+ window->text_context = ltk_text_context_create(window, window->theme.font);
XClearWindow(window->dpy, window->xwindow);
XMapRaised(window->dpy, window->xwindow);
@@ -639,8 +640,8 @@ ltk_create_window(const char *title, int x, int y, unsigned int w, unsigned int
static void
ltk_destroy_window(ltk_window *window) {
+ ltk_text_context_destroy(window->text_context);
XDestroyWindow(window->dpy, window->xwindow);
- ltk_cleanup_text();
XCloseDisplay(window->dpy);
/* FIXME: This doesn't work because it can sometimes be a readonly
string from ltk_window_setup_theme_defaults! */
diff --git a/src/scrollbar.c b/src/scrollbar.c
@@ -160,7 +160,7 @@ ltk_scrollbar_draw(ltk_widget *self, ltk_rect clip) {
}
ltk_surface_fill_rect(s, fg, (ltk_rect){handle_x, handle_y, handle_w, handle_h});
ltk_rect clip_final = ltk_rect_intersect(clip, rect);
- ltk_surface_copy_to_window(s, self->window, ltk_rect_relative(rect, clip_final), clip_final.x, clip_final.y);
+ ltk_surface_copy(s, self->window->surface, ltk_rect_relative(rect, clip_final), clip_final.x, clip_final.y);
}
static int
@@ -200,11 +200,12 @@ static int
ltk_scrollbar_motion_notify(ltk_widget *self, XEvent event) {
(void)self;
(void)event;
- /*
+ ltk_scrollbar *sc = (ltk_scrollbar *)self;
double scale;
int delta, max_pos;
- if (sc->widget.state != LTK_PRESSED)
+ if (self->state != LTK_PRESSED) {
return 1;
+ }
if (sc->orient == LTK_HORIZONTAL) {
delta = event.xbutton.x - sc->last_mouse_x;
max_pos = sc->virtual_size > sc->widget.rect.w ? sc->virtual_size - sc->widget.rect.w : 0;
@@ -223,7 +224,6 @@ ltk_scrollbar_motion_notify(ltk_widget *self, XEvent event) {
sc->last_mouse_y = event.xbutton.y;
if (delta > 0)
sc->callback(sc->callback_data);
- */
return 1;
}
diff --git a/src/text.h b/src/text.h
@@ -19,22 +19,39 @@
#include "color.h"
#include "graphics.h"
+#include "ltk.h"
typedef struct ltk_text_line ltk_text_line;
+/* typedef struct ltk_text_context ltk_text_context; */
-/* FIXME: remove x-specific stuff from interface */
-void ltk_init_text(const char *default_font, Display *dpy, int screen, Colormap cm);
-void ltk_cleanup_text(void);
-ltk_text_line *ltk_text_line_create(Window window, uint16_t font_size, char *text, int width, ltk_color *fg, ltk_color *bg);
-/* FIXME: either implement clip rect or remove it from arguments */
-void ltk_text_line_draw(ltk_text_line *tl, ltk_surface *s, GC gc, int x, int y, ltk_rect clip);
+/* FIXME: something to hold display, etc. to avoid circular reference between window and text context */
+
+ltk_text_context *ltk_text_context_create(ltk_window *window, char *default_font);
+void ltk_text_context_destroy(ltk_text_context *ctx);
+
+/* FIXME: allow to give length of text */
+ltk_text_line *ltk_text_line_create(ltk_text_context *ctx, uint16_t font_size, char *text, int take_over_text, int width);
void ltk_text_line_set_width(ltk_text_line *tl, int width);
void ltk_text_line_get_size(ltk_text_line *tl, int *w, int *h);
void ltk_text_line_destroy(ltk_text_line *tl);
-void ltk_text_line_change_colors(ltk_text_line *tl, ltk_color *fg, ltk_color *bg);
-#if USE_PANGO == 1
- #include <pango/pangoxft.h>
-#endif
+/* Draw the entire line to a surface. */
+void ltk_text_line_draw(ltk_text_line *tl, ltk_surface *s, ltk_color *color, int x, int y);
+
+/* Get the smallest rectangle of the line that can be drawn while covering 'clip'.
+ * The Pango backend will currently always return the full rectangle for the line
+ * because it doesn't support clipping. Other backends may just return a slightly
+ * larger rectangle so they can draw full glyphs. */
+ltk_rect ltk_text_line_get_minimal_clip_rect(ltk_text_line *tl, ltk_rect clip);
+
+/* Draw a line onto a surface at position x,y and clipped to 'clip'. Note that
+ * clipping isn't supported properly, so the drawn part of the line may be
+ * larger than 'clip'. In order to find out the exact size of the drawn section,
+ * use ltk_rect_line_get_minimal_clip_rect. */
+void ltk_text_line_draw_clipped(ltk_text_line *tl, ltk_surface *s, ltk_color *color, int x, int y, ltk_rect clip);
+
+/* FIXME: Any way to implement clipping properly? The text would need to be drawn
+ to an intermediate surface, but then we lose alpha blending with the background
+ (unless another library like cairo is used, which I want to avoid). */
#endif /* _LTK_TEXT_H_ */
diff --git a/src/text_pango.c b/src/text_pango.c
@@ -35,96 +35,87 @@
#include "text.h"
struct ltk_text_line {
+ ltk_text_context *ctx;
char *text;
- uint16_t font_size;
- int w;
- int h;
- Window window;
PangoLayout *layout;
- ltk_color *fg;
- ltk_color *bg;
+ uint16_t font_size;
};
-struct {
+struct ltk_text_context {
+ ltk_window *window;
PangoFontMap *fontmap;
PangoContext *context;
char *default_font;
- Display *dpy;
- int screen;
- Colormap cm;
-} tm = {NULL, NULL, NULL, NULL, 0, 0};
+};
void
-ltk_init_text(const char *default_font, Display *dpy, int screen, Colormap cm) {
- tm.fontmap = pango_xft_get_font_map(dpy, screen);
- tm.context = pango_font_map_create_context(tm.fontmap);
- tm.default_font = ltk_strdup(default_font);
- tm.dpy = dpy;
- tm.screen = screen;
- tm.cm = cm;
+ltk_text_context_create(ltk_window *window, const char *default_font) {
+ ltk_text_context *ctx = ltk_malloc(sizeof(ltk_text_context));
+ ctx->window = window;
+ ctx->fontmap = pango_xft_get_font_map(window->dpy, window->screen);
+ ctx->context = pango_font_map_create_context(ctx->fontmap);
+ ctx->default_font = ltk_strdup(default_font);
}
void
-ltk_cleanup_text(void) {
- if (tm.default_font) ltk_free(tm.default_font);
- /* FIXME: destroy fontmap and context */
+ltk_text_context_destroy(ltk_text_context *ctx) {
+ ltk_free(ctx->default_font);
+ g_object_unref(ctx->fontmap);
+ g_object_unref(ctx->context);
+ ltk_free(ctx);
}
void
ltk_text_line_set_width(ltk_text_line *tl, int width) {
pango_layout_set_width(tl->layout, width * PANGO_SCALE);
- /* FIXME: this is very inefficient because it immediately
- accesses the size, forcing pango to recalculate it even
- if it may never be needed before e.g. changing text */
- pango_layout_get_size(tl->layout, &tl->w, &tl->h);
- tl->w /= PANGO_SCALE;
- tl->h /= PANGO_SCALE;
- tl->w = tl->w == 0 ? 1 : tl->w;
- tl->h = tl->h == 0 ? 1 : tl->h;
-}
-
-void
-ltk_text_line_change_colors(ltk_text_line *tl, ltk_color *fg, ltk_color *bg) {
- tl->fg = fg;
- tl->bg = bg;
}
ltk_text_line *
-ltk_text_line_create(Window window, uint16_t font_size, char *text, int width, ltk_color *fg, ltk_color *bg) {
- if (!tm.context)
- ltk_fatal("ltk_text_line_create (pango): text not initialized yet");
- ltk_text_line *line = ltk_malloc(sizeof(ltk_text_line));
- line->text = text;
- line->font_size = font_size;
- line->layout = pango_layout_new(tm.context);
-
- PangoFontDescription *desc = pango_font_description_from_string(tm.default_font);
+ltk_text_line_create(ltk_text_context *ctx, uint16_t font_size, char *text, int take_over_text, int width) {
+ ltk_text_line *tl = ltk_malloc(sizeof(ltk_text_line));
+ if (take_over_text)
+ tl->text = text;
+ else
+ tl->text = ltk_strdup(text);
+ tl->font_size = font_size;
+ tl->layout = pango_layout_new(ctx->context);
+
+ PangoFontDescription *desc = pango_font_description_from_string(ctx->default_font);
pango_font_description_set_size(desc, font_size * PANGO_SCALE);
- pango_layout_set_font_description(line->layout, desc);
+ pango_layout_set_font_description(tl->layout, desc);
pango_font_description_free(desc);
- line->window = window;
- pango_layout_set_wrap(line->layout, PANGO_WRAP_WORD_CHAR);
- pango_layout_set_text(line->layout, text, -1);
- ltk_text_line_set_width(line, width);
- line->fg = fg;
- line->bg = bg;
-
- return line;
+ tl->ctx = ctx;
+ pango_layout_set_wrap(tl->layout, PANGO_WRAP_WORD_CHAR);
+ pango_layout_set_text(tl->layout, text, -1);
+ ltk_text_line_set_width(tl, width * PANGO_SCALE);
+
+ return tl;
}
-/* FIXME: bg isn't used right now */
void
-ltk_text_line_draw(ltk_text_line *tl, ltk_surface *s, GC gc, int x, int y, ltk_rect clip) {
- (void)clip; /* FIXME: use this */
- (void)gc;
+ltk_text_line_draw(ltk_text_line *tl, ltk_surface *s, ltk_color *color, int x, int y) {
XftDraw *d = ltk_surface_get_xft_draw(s);
- pango_xft_render_layout(d, &tl->fg->xftcolor, tl->layout, x * PANGO_SCALE, y * PANGO_SCALE);
+ pango_xft_render_layout(d, &color->xftcolor, tl->layout, x * PANGO_SCALE, y * PANGO_SCALE);
+}
+
+/* FIXME: any way to actually implement clipping with pango? */
+void
+ltk_text_line_draw_clipped(ltk_text_line *tl, ltk_surface *s, ltk_color *color, int x, int y, ltk_rect clip) {
+ (void)clip;
+ ltk_text_line_draw(tl, s, color, x, y);
+}
+
+ltk_rect
+ltk_text_line_get_minimal_clip_rect(ltk_text_line *tl, ltk_rect clip) {
+ (void)clip;
+ int w, h;
+ ltk_text_line_get_size(tl, &w, &h);
+ return (ltk_rect){0, 0, w, h};
}
void
ltk_text_line_get_size(ltk_text_line *tl, int *w, int *h) {
- *w = tl->w;
- *h = tl->h;
+ pango_layout_get_pixel_size(tl->layout, w, h);
}
void
diff --git a/src/text_stb.c b/src/text_stb.c
@@ -1,5 +1,3 @@
-/* FIXME: more dirty flags; cache ximages so not too much ram is used
- when a lot of text is displayed */
/*
* Copyright (c) 2017, 2018, 2020, 2022 lumidify <nobody@lumidify.org>
*
@@ -70,7 +68,7 @@ typedef struct {
} ltk_glyph;
struct ltk_text_line {
- XImage *img;
+ ltk_text_context *ctx;
char *text;
ltk_glyph *glyphs;
size_t glyph_len;
@@ -79,18 +77,14 @@ struct ltk_text_line {
int lines;
int lines_alloc;
- Window window;
-
int w_max;
int w;
int h;
int line_h;
int x_min;
int y_min;
- uint16_t font_size;
int dirty;
- ltk_color *fg;
- ltk_color *bg;
+ uint16_t font_size;
};
/* Hash definitions */
@@ -99,7 +93,8 @@ KHASH_MAP_INIT_INT(glyphinfo, ltk_glyph_info*)
/* font path, size -> glyph cache hash */
KHASH_MAP_INIT_INT(glyphcache, khash_t(glyphinfo)*)
-static struct {
+struct ltk_text_context {
+ ltk_window *window;
khash_t(glyphcache) *glyph_cache;
ltk_font **fonts;
int num_fonts;
@@ -107,33 +102,28 @@ static struct {
FcPattern *fcpattern;
ltk_font *default_font;
uint16_t font_id_cur;
- Display *dpy;
- int screen;
- Colormap cm;
-} tm = {NULL, NULL, 0, 0, NULL, NULL, 1, NULL, 0, 0};
-
+};
-static ltk_font *ltk_get_font(char *path, int index);
+static ltk_font *ltk_get_font(ltk_text_context *ctx, char *path, int index);
static ltk_glyph_info *ltk_create_glyph_info(ltk_font *font, int id,
float scale);
static void ltk_destroy_glyph_info(ltk_glyph_info *gi);
static ltk_glyph_info *ltk_get_glyph_info(ltk_font *font, int id,
float scale, khash_t(glyphinfo) *cache);
-static khash_t(glyphinfo) *ltk_get_glyph_cache(uint16_t font_id,
+static khash_t(glyphinfo) *ltk_get_glyph_cache(ltk_text_context *ctx, uint16_t font_id,
uint16_t font_size);
-static khint_t ltk_create_glyph_cache(uint16_t font_id, uint16_t font_size);
+static khint_t ltk_create_glyph_cache(ltk_text_context *ctx, uint16_t font_id, uint16_t font_size);
static void ltk_destroy_glyph_cache(khash_t(glyphinfo) *cache);
-static void ltk_load_default_font(const char *name);
static ltk_font *ltk_create_font(char *path, uint16_t id, int index);
static void ltk_destroy_font(ltk_font *font);
-static ltk_font *ltk_load_font(char *path, int index);
-static ltk_font *ltk_get_font(char *path, int index);
-static void ltk_text_to_glyphs(ltk_glyph *glyphs, int num_glyphs, char *text,
+static ltk_font *ltk_load_font(ltk_text_context *ctx, char *path, int index);
+static void ltk_load_default_font(ltk_text_context *ctx, char *default_font);
+static void ltk_text_to_glyphs(ltk_text_context *ctx, ltk_glyph *glyphs, int num_glyphs, char *text,
uint16_t font_size, int *x_min, int *y_min, int *x_max, int *y_max);
static void ltk_text_line_create_glyphs(ltk_text_line *tl);
static void ltk_text_line_draw_glyph(ltk_glyph *glyph, int x, int y,
XImage *img, XColor fg);
-static XImage *ltk_create_ximage(int w, int h, int depth, XColor bg);
+/*static XImage *ltk_create_ximage(int w, int h, int depth, XColor bg);*/
/* These unicode routines are taken from
@@ -210,29 +200,33 @@ static size_t u8_wc_toutf8(char *dest, uint32_t ch) {
}
*/
-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 = ltk_malloc(sizeof(ltk_font *));
- ltk_load_default_font(default_font);
- tm.dpy = dpy;
- tm.screen = screen;
- tm.cm = cm;
+ltk_text_context *
+ltk_text_context_create(ltk_window *window, char *default_font) {
+ ltk_text_context *ctx = ltk_malloc(sizeof(ltk_text_context));
+ ctx->window = window;
+ ctx->glyph_cache = kh_init(glyphcache);
+ ctx->fonts = ltk_malloc(sizeof(ltk_font *));
+ ctx->num_fonts = 0;
+ ctx->fonts_bufsize = 1;
+ ctx->fcpattern = NULL;
+ ltk_load_default_font(ctx, default_font);
+ ctx->font_id_cur = 1;
+ return ctx;
}
void
-ltk_cleanup_text(void) {
- for (int i = 0; i < tm.num_fonts; i++) {
- ltk_destroy_font(tm.fonts[i]);
+ltk_text_context_destroy(ltk_text_context *ctx) {
+ /* FIXME: destroy fcpattern */
+ for (int i = 0; i < ctx->num_fonts; i++) {
+ ltk_destroy_font(ctx->fonts[i]);
}
- if (!tm.glyph_cache) return;
- for (khint_t k = kh_begin(tm.glyph_cache); k != kh_end(tm.glyph_cache); k++) {
- if (kh_exist(tm.glyph_cache, k)) {
- ltk_destroy_glyph_cache(kh_value(tm.glyph_cache, k));
+ if (!ctx->glyph_cache) return;
+ for (khint_t k = kh_begin(ctx->glyph_cache); k != kh_end(ctx->glyph_cache); k++) {
+ if (kh_exist(ctx->glyph_cache, k)) {
+ ltk_destroy_glyph_cache(kh_value(ctx->glyph_cache, k));
}
}
- kh_destroy(glyphcache, tm.glyph_cache);
+ kh_destroy(glyphcache, ctx->glyph_cache);
}
static ltk_glyph_info *
@@ -274,24 +268,24 @@ ltk_get_glyph_info(ltk_font *font, int id, float scale, khash_t(glyphinfo) *cach
}
static khash_t(glyphinfo) *
-ltk_get_glyph_cache(uint16_t font_id, uint16_t font_size) {
+ltk_get_glyph_cache(ltk_text_context *ctx, uint16_t font_id, uint16_t font_size) {
khint_t k;
uint32_t attr = ((uint32_t)font_id << 16) + font_size;
- k = kh_get(glyphcache, tm.glyph_cache, attr);
- if (k == kh_end(tm.glyph_cache)) {
- k = ltk_create_glyph_cache(font_id, font_size);
+ k = kh_get(glyphcache, ctx->glyph_cache, attr);
+ if (k == kh_end(ctx->glyph_cache)) {
+ k = ltk_create_glyph_cache(ctx, font_id, font_size);
}
- return kh_value(tm.glyph_cache, k);
+ return kh_value(ctx->glyph_cache, k);
}
static khint_t
-ltk_create_glyph_cache(uint16_t font_id, uint16_t font_size) {
+ltk_create_glyph_cache(ltk_text_context *ctx, uint16_t font_id, uint16_t font_size) {
khash_t(glyphinfo) *cache = kh_init(glyphinfo);
int ret;
khint_t k;
/* I guess I can just ignore ret for now */
- k = kh_put(glyphcache, tm.glyph_cache, ((uint32_t)font_id << 16) + font_size, &ret);
- kh_value(tm.glyph_cache, k) = cache;
+ k = kh_put(glyphcache, ctx->glyph_cache, ((uint32_t)font_id << 16) + font_size, &ret);
+ kh_value(ctx->glyph_cache, k) = cache;
return k;
}
@@ -307,24 +301,24 @@ ltk_destroy_glyph_cache(khash_t(glyphinfo) *cache) {
}
static void
-ltk_load_default_font(const char *name) {
+ltk_load_default_font(ltk_text_context *ctx, char *name) {
FcPattern *match;
FcResult result;
char *file;
int index;
/* FIXME: Get rid of this stupid cast somehow */
- tm.fcpattern = FcNameParse((const FcChar8 *)name);
- /*tm.fcpattern = FcPatternCreate();*/
- FcPatternAddString(tm.fcpattern, FC_FONTFORMAT, (const FcChar8 *)"truetype");
- FcConfigSubstitute(NULL, tm.fcpattern, FcMatchPattern);
- FcDefaultSubstitute(tm.fcpattern);
- match = FcFontMatch(NULL, tm.fcpattern, &result);
+ ctx->fcpattern = FcNameParse((const FcChar8 *)name);
+ /*ctx->fcpattern = FcPatternCreate();*/
+ FcPatternAddString(ctx->fcpattern, FC_FONTFORMAT, (const FcChar8 *)"truetype");
+ FcConfigSubstitute(NULL, ctx->fcpattern, FcMatchPattern);
+ FcDefaultSubstitute(ctx->fcpattern);
+ match = FcFontMatch(NULL, ctx->fcpattern, &result);
FcPatternGetString(match, FC_FILE, 0, (FcChar8 **) &file);
FcPatternGetInteger(match, FC_INDEX, 0, &index);
- tm.default_font = ltk_get_font(file, index);
+ ctx->default_font = ltk_get_font(ctx, file, index);
FcPatternDestroy(match);
}
@@ -354,35 +348,35 @@ ltk_destroy_font(ltk_font *font) {
}
static ltk_font *
-ltk_load_font(char *path, int index) {
- ltk_font *font = ltk_create_font(path, tm.font_id_cur++, index);
- if (tm.num_fonts == tm.fonts_bufsize) {
- ltk_font **new = ltk_realloc(tm.fonts, tm.fonts_bufsize * 2 * sizeof(ltk_font *));
- tm.fonts = new;
- tm.fonts_bufsize *= 2;
+ltk_load_font(ltk_text_context *ctx, char *path, int index) {
+ ltk_font *font = ltk_create_font(path, ctx->font_id_cur++, index);
+ if (ctx->num_fonts == ctx->fonts_bufsize) {
+ ltk_font **new = ltk_realloc(ctx->fonts, ctx->fonts_bufsize * 2 * sizeof(ltk_font *));
+ ctx->fonts = new;
+ ctx->fonts_bufsize *= 2;
}
- tm.fonts[tm.num_fonts] = font;
- tm.num_fonts++;
+ ctx->fonts[ctx->num_fonts] = font;
+ ctx->num_fonts++;
return font;
}
static ltk_font *
-ltk_get_font(char *path, int index) {
+ltk_get_font(ltk_text_context *ctx, char *path, int index) {
ltk_font *font = NULL;
- for (int i = 0; i < tm.num_fonts; i++) {
- if (tm.fonts[i]->index == index &&
- strcmp(tm.fonts[i]->path, path) == 0) {
- font = tm.fonts[i];
+ for (int i = 0; i < ctx->num_fonts; i++) {
+ if (ctx->fonts[i]->index == index &&
+ strcmp(ctx->fonts[i]->path, path) == 0) {
+ font = ctx->fonts[i];
break;
}
}
if (!font)
- font = ltk_load_font(path, index);
+ font = ltk_load_font(ctx, path, index);
return font;
}
static void
-ltk_text_to_glyphs(ltk_glyph *glyphs, int num_glyphs, char *text, uint16_t font_size,
+ltk_text_to_glyphs(ltk_text_context *ctx, ltk_glyph *glyphs, int num_glyphs, char *text, uint16_t font_size,
int *x_min, int *y_min, int *x_max, int *y_max) {
uint32_t c1, c2 = 0;
int gid;
@@ -396,8 +390,8 @@ ltk_text_to_glyphs(ltk_glyph *glyphs, int num_glyphs, char *text, uint16_t font_
*x_min = INT_MAX, *x_max = INT_MIN, *y_min = INT_MAX, *y_max = INT_MIN;
ltk_glyph_info *ginfo;
- ltk_font *font = tm.default_font;
- khash_t(glyphinfo) *glyph_cache = ltk_get_glyph_cache(font->id, font_size);
+ ltk_font *font = ctx->default_font;
+ khash_t(glyphinfo) *glyph_cache = ltk_get_glyph_cache(ctx, font->id, font_size);
scale = stbtt_ScaleForPixelHeight(&font->info, font_size);
stbtt_GetFontVMetrics(&font->info, &ascent, &descent, &line_gap);
@@ -421,8 +415,8 @@ ltk_text_to_glyphs(ltk_glyph *glyphs, int num_glyphs, char *text, uint16_t font_
match = FcFontMatch(NULL, pat, &result);
FcPatternGetString(match, FC_FILE, 0, &file);
FcPatternGetInteger(match, FC_INDEX, 0, &index);
- font = ltk_get_font((char *)file, index);
- glyph_cache = ltk_get_glyph_cache(font->id, font_size);
+ font = ltk_get_font(ctx, (char *)file, index);
+ glyph_cache = ltk_get_glyph_cache(ctx, font->id, font_size);
FcPatternDestroy(match);
FcPatternDestroy(pat);
gid = stbtt_FindGlyphIndex(&font->info, c1);
@@ -477,8 +471,7 @@ ltk_unref_glyphs(ltk_glyph *glyphs, int num_glyphs) {
}
*/
-/* FIXME: Error checking that tm has been initialized */
-
+/*
static void
ltk_fill_ximage(XImage *img, int w, int h, XColor bg) {
int b;
@@ -502,9 +495,11 @@ ltk_create_ximage(int w, int h, int depth, XColor bg) {
return img;
}
+*/
/* based on http://codemadness.org/git/dwm-font/file/drw.c.html#l315 */
/* FIXME: make this work with other pixel representations */
+/* FIXME: will fail horribly if depth is not 32 */
static void
ltk_text_line_draw_glyph(ltk_glyph *glyph, int x, int y, XImage *img, XColor fg) {
double a;
@@ -562,26 +557,20 @@ ltk_text_line_break_lines(ltk_text_line *tl) {
i++;
}
tl->h = tl->line_h * tl->lines;
+ tl->dirty = 0;
}
-static void
-ltk_text_line_render(
- ltk_text_line *tl,
- ltk_color *bg,
- ltk_color *fg)
-{
- /* FIXME: just keep reference to ltk_window so this isn't necessary */
- XWindowAttributes attrs;
- XGetWindowAttributes(tm.dpy, tl->window, &attrs);
- int depth = attrs.depth;
- /* FIXME: maybe don't destroy if old image is big enough? */
- if (!tl->img || tl->img->width != tl->w || tl->img->height != tl->h) {
- if (tl->img)
- XDestroyImage(tl->img);
- tl->img = ltk_create_ximage(tl->w, tl->h, depth, bg->xcolor);
- } else {
- ltk_fill_ximage(tl->img, tl->w, tl->h, bg->xcolor);
- }
+/* FIXME: improve color handling - where passed as pointer, where as value?
+ In certain cases, it's important to deallocate the color in the end
+ (if the x server doesn't support truecolor - I'm not sure right now if
+ this is the right terminology, but it's something like that) */
+
+void
+ltk_text_line_draw(ltk_text_line *tl, ltk_surface *s, ltk_color *color, int x, int y) {
+ if (tl->dirty)
+ ltk_text_line_break_lines(tl);
+ Drawable d = ltk_surface_get_drawable(s);
+ XImage *img = XGetImage(tl->ctx->window->dpy, d, x, y, tl->w, tl->h, 0xFFFFFF, ZPixmap);
int last_break = 0;
for (int i = 0; i < tl->lines; i++) {
@@ -593,55 +582,42 @@ ltk_text_line_render(
for (int j = last_break; j < next_break; j++) {
int x = tl->glyphs[j].x - tl->glyphs[last_break].x;
int y = tl->glyphs[j].y - tl->y_min + tl->line_h * i;
- ltk_text_line_draw_glyph(&tl->glyphs[j], x, y, tl->img, fg->xcolor);
+ ltk_text_line_draw_glyph(&tl->glyphs[j], x, y, img, color->xcolor);
}
last_break = next_break;
}
- tl->dirty = 0;
+ XPutImage(tl->ctx->window->dpy, d, tl->ctx->window->gc, img, 0, 0, x, y, tl->w, tl->h);
+ XDestroyImage(img);
}
-/* FIXME: improve color handling - where passed as pointer, where as value?
- In certain cases, it's important to deallocate the color in the end
- (if the x server doesn't support truecolor - I'm not sure right now if
- this is the right terminology, but it's something like that) */
+/* FIXME: ACTUALLY IMPLEMENT!!! */
void
-ltk_text_line_change_colors(ltk_text_line *tl, ltk_color *fg, ltk_color *bg) {
- tl->fg = fg;
- tl->bg = bg;
- tl->dirty = 1;
-
+ltk_text_line_draw_clipped(ltk_text_line *tl, ltk_surface *s, ltk_color *color, int x, int y, ltk_rect clip) {
+ (void)clip;
+ ltk_text_line_draw(tl, s, color, x, y);
}
-/* FIXME: error checking if img is rendered yet, tm initialized, etc. */
-void
-ltk_text_line_draw(ltk_text_line *tl, ltk_surface *s, GC gc, int x, int y, ltk_rect clip) {
+ltk_rect
+ltk_text_line_get_minimal_clip_rect(ltk_text_line *tl, ltk_rect clip) {
(void)clip;
if (tl->dirty)
- ltk_text_line_render(tl, tl->bg, tl->fg);
- /*
- int xoff = clip.x - x;
- int yoff = clip.y - y;
- xoff = xoff >= 0 ? xoff : 0;
- yoff = yoff >= 0 ? yoff : 0;
- int w = clip.w > tl->w - xoff ? tl->w - xoff : clip.w;
- int h = clip.h > tl->h - yoff ? tl->h - yoff : clip.h;
- XPutImage(tm.dpy, tl->window, gc, tl->img, xoff, yoff, x + xoff, y + yoff, w, h);
- */
- Pixmap p = ltk_surface_get_pixmap(s);
- XPutImage(tm.dpy, p, gc, tl->img, 0, 0, x, y, tl->w, tl->h);
+ ltk_text_line_break_lines(tl);
+ return (ltk_rect){0, 0, tl->w, tl->h};
}
void
ltk_text_line_set_width(ltk_text_line *tl, int width) {
/* FIXME: clarify what the difference between w_max and w is */
+ /* FIXME: tl->w could be made slightly less than tl->w_max depending on breaking */
tl->w_max = width;
tl->w = width;
- ltk_text_line_break_lines(tl);
tl->dirty = 1;
}
void
ltk_text_line_get_size(ltk_text_line *tl, int *w, int *h) {
+ if (tl->dirty)
+ ltk_text_line_break_lines(tl);
*w = tl->w;
*h = tl->h;
}
@@ -649,7 +625,7 @@ ltk_text_line_get_size(ltk_text_line *tl, int *w, int *h) {
static void
ltk_text_line_create_glyphs(ltk_text_line *tl) {
int x_min, x_max, y_min, y_max;
- ltk_text_to_glyphs(tl->glyphs, tl->glyph_len, tl->text, tl->font_size,
+ ltk_text_to_glyphs(tl->ctx, 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;
@@ -659,28 +635,26 @@ ltk_text_line_create_glyphs(ltk_text_line *tl) {
}
ltk_text_line *
-ltk_text_line_create(Window window, uint16_t font_size, char *text, int width, ltk_color *fg, ltk_color *bg) {
- ltk_text_line *line = ltk_malloc(sizeof(ltk_text_line));
- line->window = window;
- line->img = NULL;
- line->text = text;
- line->glyph_len = u8_strlen(text);
- line->glyphs = ltk_malloc(line->glyph_len * sizeof(ltk_glyph));
- line->font_size = font_size;
- line->w_max = width;
- ltk_text_line_create_glyphs(line);
- line->lines_alloc = line->lines = 0;
- line->line_indeces = NULL;
- ltk_text_line_break_lines(line);
- line->dirty = 1;
- line->fg = fg;
- line->bg = bg;
- return line;
+ltk_text_line_create(ltk_text_context *ctx, uint16_t font_size, char *text, int take_over_text, int width) {
+ ltk_text_line *tl = ltk_malloc(sizeof(ltk_text_line));
+ tl->ctx = ctx;
+ if (take_over_text)
+ tl->text = text;
+ else
+ tl->text = ltk_strdup(text);
+ tl->glyph_len = u8_strlen(text);
+ tl->glyphs = ltk_malloc(tl->glyph_len * sizeof(ltk_glyph));
+ tl->font_size = font_size;
+ tl->w_max = width;
+ ltk_text_line_create_glyphs(tl);
+ tl->lines_alloc = tl->lines = 0;
+ tl->line_indeces = NULL;
+ tl->dirty = 1;
+ return tl;
}
void
ltk_text_line_destroy(ltk_text_line *tl) {
- XDestroyImage(tl->img);
ltk_free(tl->text);
/* FIXME: Reference count glyph infos */
ltk_free(tl->glyphs);