commit d6e2f851b663e5db6957c3fb5c41f595c139c3c6
parent 288e467a6083a547a3996e69b6ba0ea1d430e70b
Author: lumidify <nobody@lumidify.org>
Date:   Wed, 27 May 2020 21:19:10 +0200
Somewhat improve drawing
Diffstat:
6 files changed, 31 insertions(+), 143 deletions(-)
diff --git a/NOTES b/NOTES
@@ -36,3 +36,6 @@ and creates a "failsafe" error window (just using basic
 XDrawString, etc.) to show errors (like index out of bounds,
 etc.). Still print the error, of course, in case creating
 a window doesn't work.
+
+Idea: Make interface primarily key-driven; store keybindings
+in config so they can easily be configured
diff --git a/ltk.c b/ltk.c
@@ -94,10 +94,19 @@ void ltk_mainloop(void)
 	XEvent event;
 	KeySym key;
 	char text[255];
+	int redraw = 0;
+	LtkWindow *window = NULL;
 
+	/* FIXME: compress motion events */
 	while (1) {
-		XNextEvent(ltk_global->display, &event);
-		ltk_handle_event(event);
+		if (XPending(ltk_global->display) || !redraw) {
+			XNextEvent(ltk_global->display, &event);
+			redraw = ltk_handle_event(event, &window) || redraw;
+		} else if (redraw && window) {
+			ltk_redraw_window(window);
+			redraw = 0;
+			window = NULL;
+		}
 	}
 }
 
@@ -177,10 +186,10 @@ void ltk_destroy_window(LtkWindow * window)
 	ltk_global->window_num--;
 }
 
-void ltk_window_other_event(void *widget, XEvent event)
+int ltk_window_other_event(LtkWindow *window, XEvent event)
 {
-	LtkWindow *window = (LtkWindow *) widget;
 	LtkWidget *ptr = window->root_widget;
+	int retval = 0;
 	if (event.type == ConfigureNotify) {
 		unsigned int w, h;
 		w = event.xconfigure.width;
@@ -194,16 +203,15 @@ void ltk_window_other_event(void *widget, XEvent event)
 			ptr->rect.w = w;
 			ptr->rect.h = h;
 			ptr->resize(ptr, orig_w, orig_h);
-			ltk_redraw_window(window);
+			retval = 1;
 		}
-	}
-	if (event.type == Expose && event.xexpose.count == 0) {
-		ltk_redraw_window(window);
-	}
-	if (event.type == ClientMessage
+	} else if (event.type == Expose && event.xexpose.count == 0) {
+		retval = 1;
+	} else if (event.type == ClientMessage
 	    && event.xclient.data.l[0] == ltk_global->wm_delete_msg) {
 		ltk_remove_window(window);
 	}
+	return retval;
 }
 
 void ltk_window_ini_handler(LtkTheme *theme, const char *prop, const char *value)
@@ -405,14 +413,13 @@ void ltk_motion_notify_event(void *widget, XEvent event)
 		ptr->motion_notify(ptr, event);
 }
 
-void ltk_handle_event(XEvent event)
+int ltk_handle_event(XEvent event, LtkWindow **window)
 {
-	LtkWindow *window;
 	LtkWidget *root_widget;
 	int k = kh_get(winhash, ltk_global->window_hash, event.xany.window);
-	window = kh_value(ltk_global->window_hash, k);
-	if (!window) return;
-	root_widget = window->root_widget;
+	*window = kh_value(ltk_global->window_hash, k);
+	if (!*window) return 0;
+	root_widget = (*window)->root_widget;
 	switch (event.type) {
 	case KeyPress:
 		break;
@@ -432,7 +439,8 @@ void ltk_handle_event(XEvent event)
 		break;
 	default:
 		/* FIXME: users should be able to register other events like closing the window */
-		if (window->other_event)
-			window->other_event(window, event);
+		if ((*window)->other_event)
+			return (*window)->other_event(*window, event);
 	}
+	return 0;
 }
diff --git a/ltk.h b/ltk.h
@@ -83,7 +83,7 @@ typedef struct LtkWindow {
 	Window xwindow;
 	GC gc;
 	void *root_widget;
-	void (*other_event) (void *, XEvent event);
+	int (*other_event) (LtkWindow *, XEvent event);
 	LtkRect rect;
 } LtkWindow;
 
@@ -136,7 +136,7 @@ void ltk_remove_window(LtkWindow * window);
 
 void ltk_destroy_window(LtkWindow * window);
 
-void ltk_window_other_event(void *widget, XEvent event);
+int ltk_window_other_event(LtkWindow *window, XEvent event);
 
 void ltk_destroy_theme(LtkTheme * theme);
 
@@ -159,6 +159,6 @@ void ltk_mouse_release_event(void *widget, XEvent event);
 
 void ltk_motion_notify_event(void *widget, XEvent event);
 
-void ltk_handle_event(XEvent event);
+int ltk_handle_event(XEvent event, LtkWindow **window);
 
 #endif
diff --git a/text_buffer.c b/text_buffer.c
@@ -21,7 +21,6 @@
  * SOFTWARE.
  */
 
-#include <sys/time.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <stdint.h>
@@ -79,10 +78,6 @@ ltk_text_line_cleanup_soft_lines(struct ltk_array_line *soft_lines, int old_len)
 
 void
 ltk_text_line_wrap(struct ltk_text_line *tl, int max_width) {
-	struct timeval t1, t2;
-	gettimeofday(&t1, NULL);
-	printf("wrap1: %d, %d\n", t1.tv_sec, t1.tv_usec);
-
 	tl->w_wrapped = max_width;
 	int old_len = tl->soft_lines->len;
 	tl->soft_lines->len = 0;
@@ -252,9 +247,6 @@ ltk_text_line_wrap(struct ltk_text_line *tl, int max_width) {
 	else
 		tl->w_wrapped = max_width;
 	tl->h_wrapped = tl->soft_lines->len * tl->h;
-
-	gettimeofday(&t2, NULL);
-	printf("wrap2: %d, %d, diff: %d\n", t2.tv_sec, t2.tv_usec, t2.tv_usec - t1.tv_usec);
 }
 
 XImage *
@@ -309,9 +301,6 @@ ltk_text_line_render(
 	XColor fg,
 	XColor bg)
 {
-	struct timeval t1, t2;
-	gettimeofday(&t1, NULL);
-	printf("render1: %d, %d\n", t1.tv_sec, t1.tv_usec);
 	LtkGlyph *glyph;
 	int par_is_rtl = tl->dir == HB_DIRECTION_RTL;
 
@@ -389,8 +378,6 @@ ltk_text_line_render(
 		ltk_array_resize_int(sl->glyph_pos, sl->glyph_pos->len);
 		ltk_array_resize_uint32(sl->glyph_clusters, sl->glyph_clusters->len);
 	}
-	gettimeofday(&t2, NULL);
-	printf("render2: %d, %d, diff: %d\n", t2.tv_sec, t2.tv_usec, t2.tv_usec - t1.tv_usec);
 	return img;
 }
 
@@ -638,8 +625,6 @@ ltk_text_line_itemize(struct ltk_text_line *tl) {
 static void
 ltk_text_run_shape(LtkTextManager *tm, struct ltk_text_run *tr,
     struct ltk_text_line *tl, uint16_t font_size, uint16_t font_id, int *ret_y_max) {
-	struct timeval t1, t2;
-	gettimeofday(&t1, NULL);
 	khash_t(glyphinfo) *glyph_cache;
 	khint_t k;
 
@@ -668,8 +653,6 @@ ltk_text_run_shape(LtkTextManager *tm, struct ltk_text_run *tr,
 	hb_shape(tr->font->hb, buf, NULL, 0);
 	ginf = hb_buffer_get_glyph_infos(buf, &tr->num_glyphs);
 	gpos = hb_buffer_get_glyph_positions(buf, &tr->num_glyphs);
-	gettimeofday(&t2, NULL);
-	printf("hb_shape: %d, %d, diff: %d\n", t2.tv_sec, t2.tv_usec, t2.tv_usec - t1.tv_usec);
 	float scale = stbtt_ScaleForMappingEmToPixels(&tr->font->info, font_size);
 
 	int x_min = INT_MAX, x_max = INT_MIN, y_min = INT_MAX, y_max = INT_MIN;
@@ -721,8 +704,6 @@ ltk_text_run_shape(LtkTextManager *tm, struct ltk_text_run *tr,
 	*ret_y_max = y_max;
 
 	tr->font->refs++;
-	gettimeofday(&t2, NULL);
-	printf("run_shape: %d\n", t2.tv_usec - t1.tv_usec);
 }
 
 static void
@@ -732,10 +713,8 @@ ltk_text_line_shape(LtkTextManager *tm, struct ltk_text_line *tl) {
 	int y_max;
 	int y_max_overall = INT_MIN;
 	int y_min_overall = INT_MAX;
-	struct timeval t1, t2;
 	while (run) {
 		/* Question: Why does this not work with FcPatternDuplicate? */
-		gettimeofday(&t1, NULL);
 		FcPattern *pat = FcPatternCreate();
 		FcPattern *match;
 		FcResult result;
@@ -756,8 +735,6 @@ ltk_text_line_shape(LtkTextManager *tm, struct ltk_text_line *tl) {
 		run->font = kh_value(tm->font_cache, k);
 		FcPatternDestroy(match);
 		FcPatternDestroy(pat);
-		gettimeofday(&t2, NULL);
-		printf("fontconfig: %d\n", t2.tv_usec - t1.tv_usec);
 		ltk_text_run_shape(tm, run, tl, tl->font_size, font_id, &y_max);
 		if (y_max_overall < y_max)
 			y_max_overall = y_max;
@@ -828,31 +805,18 @@ ltk_text_line_destroy_runs(struct ltk_text_run *runs) {
 static void
 ltk_text_line_recalculate(LtkTextManager *tm, struct ltk_text_line *tl) {
 	FriBidiCharType par_dir = FRIBIDI_TYPE_ON;
-	struct timeval t1, t2;
-	gettimeofday(&t1, NULL);
-	printf("fribidi1: %d, %d\n", t1.tv_sec, t1.tv_usec);
 	fribidi_log2vis(
 	    tl->log_buf->buf, tl->log_buf->len,
 	    &par_dir, tl->vis_buf->buf, tl->log2vis->buf, tl->vis2log->buf, tl->bidi_levels->buf
 	);
-	gettimeofday(&t2, NULL);
-	printf("fribidi2: %d, %d, diff: %d\n", t2.tv_sec, t2.tv_usec, t2.tv_usec - t1.tv_usec);
 	if (FRIBIDI_IS_RTL(par_dir))
 		tl->dir = HB_DIRECTION_RTL;
 	else
 		tl->dir = HB_DIRECTION_LTR;
 	struct ltk_text_run *old_runs = tl->first_run;
-	gettimeofday(&t1, NULL);
-	printf("itemize1: %d, %d\n", t1.tv_sec, t1.tv_usec);
 	ltk_text_line_itemize(tl);
-	gettimeofday(&t2, NULL);
-	printf("itemize2: %d, %d, diff: %d\n", t2.tv_sec, t2.tv_usec, t2.tv_usec - t1.tv_usec);
 	struct ltk_text_run *cur = tl->first_run;
-	gettimeofday(&t1, NULL);
-	printf("shape1: %d, %d\n", t1.tv_sec, t1.tv_usec);
 	ltk_text_line_shape(tm, tl);
-	gettimeofday(&t2, NULL);
-	printf("shape2: %d, %d, diff: %d\n", t2.tv_sec, t2.tv_usec, t2.tv_usec - t1.tv_usec);
 	/* this needs to be done after shaping so the fonts, etc. aren't
 	   removed if their reference counts drop and then loaded again
 	   right afterwards */
diff --git a/text_common.c b/text_common.c
@@ -328,83 +328,3 @@ ltk_destroy_glyph(LtkGlyph *glyph, khash_t(glyphinfo) *cache)
 	}
 	free(glyph);
 }
-
-#if 0
-/* based on http://codemadness.org/git/dwm-font/file/drw.c.html#l315 */
-XImage *
-ltk_render_text_line(
-	LtkTextLine *tl,
-	Display *dpy,
-	Window window,
-	GC gc,
-	Colormap colormap,
-	XColor fg,
-	XColor bg)
-{
-	XWindowAttributes attrs;
-	XGetWindowAttributes(dpy, window, &attrs);
-	int depth = attrs.depth;
-	XImage *img = XCreateImage(dpy, CopyFromParent, depth, ZPixmap, 0, NULL, tl->w, tl->h, 32, 0);
-	img->data = calloc(img->bytes_per_line, img->height);
-	XInitImage(img);
-	int b;
-	for (int i = 0; i < tl->h; i++) {
-		b = img->bytes_per_line * i;
-		for (int j = 0; j < tl->w; j++) {
-			img->data[b++] = bg.blue / 257;
-			img->data[b++] = bg.green / 257;
-			img->data[b++] = bg.red / 257;
-			b++;
-		}
-	}
-
-	LtkTextSegment *ts = tl->start_segment;
-	int x = 0;
-	int y = 0;
-	int is_hor = HB_DIRECTION_IS_HORIZONTAL(ts->dir);
-	do {
-		if (is_hor) {
-			y = tl->h - tl->y_max;
-			ltk_render_text_segment(ts, x + ts->start_x, y, img, fg);
-			x += ts->w;
-		} else {
-			x = tl->w - tl->x_max;
-			ltk_render_text_segment(ts, x, y + ts->start_y, img, fg);
-			y += ts->h;
-		}
-	} while (ts = ts->next);
-
-	return img;
-}
-
-void
-ltk_render_text_segment(
-	LtkTextSegment *ts,
-	unsigned int start_x,
-	unsigned int start_y,
-	XImage *img,
-	XColor fg)
-{
-	LtkGlyph *glyph = ts->start_glyph;
-	int x_cur = start_x;
-	int y_cur = start_y;
-	int x, y;
-	double a;
-	int b;
-	do {
-		x = x_cur + glyph->info->xoff + glyph->x_offset;
-		y = y_cur + glyph->info->yoff - glyph->y_offset;
-		for (int i = 0; i < glyph->info->h; i++) {
-			for (int j = 0; j < glyph->info->w; j++) {
-				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;
-			}
-		}
-		x_cur += glyph->x_advance;
-		y_cur -= glyph->y_advance;
-	} while (glyph = glyph->next);
-}
-#endif
diff --git a/text_common.h b/text_common.h
@@ -61,7 +61,6 @@ typedef struct _LtkGlyph {
 	int x_abs;
 	int y_abs;
 	uint32_t cluster; /* index of char in original text - from harfbuzz */
-	struct _LtkGlyph *next;
 } LtkGlyph;
 
 /* Hash definitions */
@@ -116,10 +115,4 @@ uint16_t ltk_get_font(LtkTextManager *tm, char *path);
 
 void ltk_destroy_glyph(LtkGlyph *glyph, khash_t(glyphinfo) *cache);
 
-/*
-XImage *ltk_render_text_line(LtkTextLine *tl, Display *dpy, Window window, GC gc, Colormap colormap, XColor fg, XColor bg);
-
-void ltk_render_text_segment(LtkTextSegment *ts, unsigned int start_x, unsigned int start_y, XImage *img, XColor fg);
-*/
-
 #endif /* _TEXT_COMMON_H_ */