commit 02f8e7bfa579c4947e8cab78a38f6b2344d4d123
parent 487c86781fe1af79c0677565dea2aa35049c082c
Author: lumidify <nobody@lumidify.org>
Date:   Wed, 13 May 2020 18:36:41 +0200
Add various destroy functions for textedit
Diffstat:
2 files changed, 70 insertions(+), 14 deletions(-)
diff --git a/textedit_wip.c b/textedit_wip.c
@@ -49,7 +49,7 @@ LTK_ARRAY_INIT_IMPL(int, int)
 LTK_STACK_INIT_IMPL(script, int, hb_script_t, pair_index, script);
 
 /* based on http://codemadness.org/git/dwm-font/file/drw.c.html#l315 */
-XImage *
+void
 ltk_render_text_line(
 	struct ltk_text_line *tl,
 	int max_width,
@@ -88,20 +88,21 @@ ltk_render_text_line(
 		}
 	} while (cur = cur->next);
 
+	if (tl->img) XDestroyImage(tl->img);
 	XWindowAttributes attrs;
 	XGetWindowAttributes(dpy, window, &attrs);
 	int depth = attrs.depth;
-	XImage *img = XCreateImage(dpy, CopyFromParent, depth, ZPixmap, 0, NULL, max_width, tl->h * tl->wrap_indeces->len, 32, 0);
-	img->data = calloc(img->bytes_per_line, img->height);
-	XInitImage(img);
+	tl->img = XCreateImage(dpy, CopyFromParent, depth, ZPixmap, 0, NULL, max_width, tl->h * tl->wrap_indeces->len, 32, 0);
+	tl->img->data = calloc(img->bytes_per_line, img->height);
+	XInitImage(tl->img);
 
 	int b;
 	for (int i = 0; i < tl->h * tl->wrap_indeces->len; i++) {
-		b = img->bytes_per_line * i;
+		b = tl->img->bytes_per_line * i;
 		for (int j = 0; j < max_width; j++) {
-			img->data[b++] = bg.blue / 257;
-			img->data[b++] = bg.green / 257;
-			img->data[b++] = bg.red / 257;
+			tl->img->data[b++] = bg.blue / 257;
+			tl->img->data[b++] = bg.green / 257;
+			tl->img->data[b++] = bg.red / 257;
 			b++;
 		}
 	}
@@ -111,6 +112,7 @@ ltk_render_text_line(
 	int cur_line_x = 0;
 	int cur_line = 0;
 	LtkGlyph *glyph;
+	/* FIXME: Ints are compared with size_t's in various places. Maybe I should fix that. */
 	/* FIXME: how should an empty line be handled? This doesn't use a do-for
 	   loop in case tl->first_run is NULL, but I should probably decide what
 	   to do in that case */
@@ -126,18 +128,16 @@ ltk_render_text_line(
 			y = glyph->y_abs + tl->h * cur_line;
 			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;
+					b = (y + i) * tl->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;
+					tl->img->data[b] = (fg.blue * a + (1 - a) * (uint16_t)tl->img->data[b] * 257) / 257;
+					tl->img->data[b + 1] = (fg.green * a + (1 - a) * (uint16_t)tl->img->data[b + 1] * 257) / 257;
+					tl->img->data[b + 2] = (fg.red * a + (1 - a) * (uint16_t)tl->img->data[b + 2] * 257) / 257;
 				}
 			}
 		}
 		cur = cur->next;
 	}
-
-	return img;
 }
 
 /*
@@ -360,6 +360,7 @@ ltk_text_run_shape(LtkTextManager *tm, struct ltk_text_run *tr,
 	khash_t(glyphinfo) *glyph_cache;
 	khint_t k;
 
+	tr->font_id = font_id;
 	uint32_t attr = font_id << 16 + font_size;
 	/* FIXME: turn this into ltk_get_glyph_cache */
 	k = kh_get(glyphcache, tm->glyph_cache, attr);
@@ -502,6 +503,45 @@ ltk_text_line_shape(LtkTextManager *tm, struct ltk_text_line *tl) {
 	}
 }
 
+/* FIXME: Don't destroy fonts, etc. every time the line is recalculated */
+/* Maybe decrease font refs but don't destroy until after the runs have been re-shaped */
+void
+ltk_text_run_destroy(struct ltk_text_line *tl, struct ltk_text_run *tr) {
+	khash_t(glyphinfo) *gcache;
+	LtkFont *font;
+	LtkGlyph *glyph;
+	khint_t k;
+	k = kh_get(glyphinfo, ltk_global->tm->glyph_cache, tr->font_id << 16 + tl->font_size);
+	gcache = kh_value(ltk_global->tm->glyph_cache, k);
+	for (int i = 0; i < tr->len; i++) {
+		glyph = tr->glyphs[i];
+		if (--glyph->info->refs < 1) {
+			k = kh_get(glyphinfo, cache, glyph->info->id);
+			kh_del(glyphinfo, cache, k);
+			ltk_destroy_glyph_info(glyph->info);
+		}
+	}
+	k = kh_get(fontstruct, ltk_global->tm->font_cache, tr->font_id);
+	font = kh_value(ltk_global->tm->font_cache, k);
+	if (--font->refs < 1) {
+		kh_del(fontstruct, ltk_global->tm->font_cache, k);
+		ltk_destroy_font(font);
+	}
+	free(tr->glyphs);
+	free(tr);
+}
+
+void
+ltk_text_line_destroy_runs(struct ltk_text_line *tl) {
+	struct ltk_text_run *cur, *last;
+	cur = tl->first_run;
+	while (cur) {
+		last = cur;
+		ltk_text_run_destroy(cur);
+		cur = last->next;
+	}
+}
+
 static void
 ltk_text_line_recalculate(LtkTextManager *tm, struct ltk_text_line *tl) {
 	ltk_gap_buffer_clear_uint32(tl->vis_buf);
@@ -590,3 +630,17 @@ ltk_text_buffer_create(void) {
 	buf->cur_line = buf->head;
 	buf->line_gap = 0;
 }
+
+void
+ltk_text_line_destroy(struct ltk_text_line *tl) {
+	ltk_gap_buffer_destroy_uint32(tl->log_buf);
+	ltk_gap_buffer_destroy_uint32(tl->vis_buf);
+	ltk_gap_buffer_destroy_script(tl->scripts);
+	ltk_gap_buffer_destroy_int(tl->log2vis);
+	ltk_gap_buffer_destroy_int(tl->vis2log);
+	ltk_array_destroy_level(tl->bidi_levels);
+	ltk_array_destroy_int(tl->wrap_indeces);
+	ltk_text_line_destroy_runs(tl);
+	if (tl->img) XDestroyImage(tl->img);
+	free(tl);
+}
diff --git a/textedit_wip.h b/textedit_wip.h
@@ -55,6 +55,7 @@ struct ltk_text_run {
 	int start_y;
 	int w;
 	LtkFont *font;
+	uint16_t font_id;
 	hb_script_t script;
 	hb_direction_t dir;
 }
@@ -79,6 +80,7 @@ struct ltk_text_line {
 	int y_min;
 	int w;
 	int h;
+	XImage *img;
 };
 
 struct ltk_text_buffer {