ltkx

GUI toolkit for X11 (WIP)
git clone git://lumidify.org/ltkx.git
Log | Files | Refs | README | LICENSE

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:
Mtextedit_wip.c | 82+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++--------------
Mtextedit_wip.h | 2++
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 {