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 {