ltkx

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

commit b7cef33142db6ea0ca0df918b86eae9c282b6230
parent 48e6e0b3b9804877d23cf36c1390352115340689
Author: lumidify <nobody@lumidify.org>
Date:   Wed, 13 May 2020 16:47:39 +0200

Calculate absolute positions of glyphs correctly

Diffstat:
Mtext-hb.c | 5+++++
Mtextedit_wip.c | 91+++++++++++++++++++++++++++++++++----------------------------------------------
Mtextedit_wip.h | 14+++-----------
3 files changed, 46 insertions(+), 64 deletions(-)

diff --git a/text-hb.c b/text-hb.c @@ -273,6 +273,9 @@ ltk_create_text_segment(LtkTextManager *tm, uint32_t *text, unsigned int len, ui y_advance doesn't really do much there. I dunno, at least *something* works now... */ /* FIXME: THIS PROBABLY DOESN'T REALLY WORK */ + /* Wait, why do I calculate abs here and don't use it while rendering? */ + /* Oh, it can't be calculated after figuring out the max and min points + of the entire line */ if (HB_DIRECTION_IS_HORIZONTAL(dir)) { x2_abs = x1_abs + glyph->x_advance; y2_abs = y1_abs + glyph->info->h; @@ -362,6 +365,7 @@ ltk_render_text_line( int is_hor = HB_DIRECTION_IS_HORIZONTAL(ts->dir); do { if (is_hor) { + printf("%d\n", ts->start_x); y = tl->h - tl->y_max; ltk_render_text_segment(ts, x + ts->start_x, y, img, fg); x += ts->w; @@ -392,6 +396,7 @@ ltk_render_text_segment( do { x = x_cur + glyph->info->xoff + glyph->x_offset; y = y_cur + glyph->info->yoff - glyph->y_offset; + printf("%d %d; %d %d\n", x, y, glyph->x_abs, glyph->y_abs); 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; diff --git a/textedit_wip.c b/textedit_wip.c @@ -63,7 +63,7 @@ ltk_render_text_line( int cur_x = 0, cur_y = 0; int par_is_rtl = FRIBIDI_IS_RTL(tl->dir); ltk_array_clear_int(tl->wrap_indeces); - tl->wrap_num = 0; + ltk_array_append_int(tl->wrap_indeces, 0); /* FIXME: wrap bidi text properly */ struct ltk_text_run *cur = tl->first_run; @@ -81,8 +81,8 @@ ltk_render_text_line( } } i = j; - ltk_array_append_int(tl->wrap_indeces, cur->start_index + i); - tl->wrap_num++; + /* FIXME: handle case that this is the same as the last index */ + ltk_array_append_int(tl->wrap_indeces, cur->glyphs[i].cluster); cur_x = 0; } } @@ -91,14 +91,14 @@ ltk_render_text_line( 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_num + 1), 32, 0); + 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); int b; - for (int i = 0; i < tl->h; i++) { + for (int i = 0; i < tl->h * tl->wrap_indeces->len; i++) { b = img->bytes_per_line * i; - for (int j = 0; j < tl->w; j++) { + 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; @@ -362,9 +362,11 @@ ltk_text_line_itemize(struct ltk_text_line *tl) { tl->last_run = cur_run; } +/* FIXME: return start_x, etc. instead of saving in struct text run */ 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) { + struct ltk_text_line *tl, uint16_t font_size, uint16_t font_id, + int *ret_x_max, int *ret_y_max) { khash_t(glyphinfo) *glyph_cache; khint_t k; @@ -435,8 +437,6 @@ ltk_text_run_shape(LtkTextManager *tm, struct ltk_text_run *tr, x2_abs = x1_abs + glyph->info->w; y2_abs = y1_abs - glyph->y_advance; } - glyph->x_abs = x1_abs; - glyph->y_abs = y1_abs; if (x1_abs < x_min) x_min = x1_abs; if (y1_abs < y_min) y_min = y1_abs; if (x2_abs > x_max) x_max = x2_abs; @@ -447,11 +447,7 @@ ltk_text_run_shape(LtkTextManager *tm, struct ltk_text_run *tr, tr->start_x = -x_min; tr->start_y = -y_min; tr->w = x_max - x_min; - tr->h = y_max - y_min; - tr->x_min = x_min; - tr->y_min = y_min; - tr->x_max = x_max; - tr->y_max = y_max; + *ret_y_max = y_max; tr->font->refs++; } @@ -459,6 +455,10 @@ ltk_text_run_shape(LtkTextManager *tm, struct ltk_text_run *tr, static void ltk_text_line_shape(LtkTextManager *tm, struct ltk_text_line *tl) { struct ltk_text_run *run = tl->runs; + tl->y_max = INT_MIN; + tl->y_min = INT_MAX; + tl->w = tl->h = 0; + int x_max, y_max; while (run) { FcPattern *pat = FcPatternDuplicate(tm->fcpattern); FcPattern *match; @@ -479,47 +479,33 @@ ltk_text_line_shape(LtkTextManager *tm, struct ltk_text_line *tl) { run->font = kh_value(tm->font_cache, k); FcPatternDestroy(match); FcPatternDestroy(pat); - ltk_text_run_shape(tm, run, tl->font_size, font_id); + ltk_text_run_shape(tm, run, tl->font_size, font_id, &y_max); + if (tl->y_max < y_max) + tl->y_max = y_max; + /* tr->start_y is -y_min */ + if (tl->y_min > -tr->start_y) + tl->y_min = -tr->start_y; + tl->w += tr->w; run = run->next; - } + }; + tl->h = tl->y_max - tl->y_min; - /* calculate width of text line - NOTE: doesn't work with mixed horizontal and vertical text */ - /* Another note: none of this works at all with vertical text anyways */ - struct ltk_text_run *tr = tl->runs; - int is_hor = HB_DIRECTION_IS_HORIZONTAL(tr->dir); - tl->y_max = tl->x_max = INT_MIN; - tl->y_min = tl->x_min = INT_MAX; - tl->w = tl->h = 0; - while (tr) { - if (HB_DIRECTION_IS_HORIZONTAL(tr->dir) != is_hor) { - (void)fprintf(stderr, "WARNING: mixed horizontal/vertical" - "text is not supported; ignoring\n"); - continue; - } - if (is_hor) { - if (tl->y_max < tr->y_max) { - tl->y_max = tr->y_max; - } - if (tl->y_min > tr->y_min) { - tl->y_min = tr->y_min; - } - tl->w += tr->w; - } else { - if (tl->x_max < tr->x_max) { - tl->x_max = tr->x_max; - } - if (tl->x_min > tr->x_min) { - tl->x_min = tr->x_min; - } - tl->h += tr->h; + /* calculate the actual position of the characters */ + run = tl->runs; + int x = 0; + LtkGlyph *glyph; + while (run) { + int cur_x = x + run->start_x; + int cur_y = tl->h - tl->y_max; /* baseline (I think?) */ + for (int i = 0; i < run->len; i++) { + glyph = run->glyphs[i]; + glyph->x_abs = cur_x + glyph->info->xoff + glyph->x_offset; + glyph->y_abs = cur_y - glyph->info->yoff - glyph->y_offset; + cur_x += glyph->x_advance; + cur_y -= glyph->y_advance; } - tr = tr->next; - } - if (is_hor) { - tl->h = tl->y_max - tl->y_min; - } else { - tl->w = tl->x_max - tl->x_min; + x += run->w; + run = run->next; } } @@ -589,7 +575,6 @@ ltk_text_line_create(void) { line->vis2log = ltk_gap_buffer_create_int(); line->bidi_levels = ltk_array_create_levels(8); line->wrap_indeces = ltk_array_create_int(1); - line->wrap_num = 0; line->runs = NULL; line->cur_run = NULL; line->next = NULL; diff --git a/textedit_wip.h b/textedit_wip.h @@ -51,15 +51,10 @@ struct ltk_text_run { struct ltk_text_run *last; size_t start_index; size_t len; - LtkFont *font; - unsigned int w; - unsigned int h; int start_x; int start_y; - int x_min; - int y_min; - int x_max; - int y_max; + int w; + LtkFont *font; hb_script_t script; hb_direction_t dir; } @@ -77,12 +72,9 @@ struct ltk_text_line { struct ltk_text_line *next; /* next text line in the buffer */ unsigned int height; /* height of the line (including wrapping) */ FribidiCharType dir; /* overall paragraph direction */ - struct ltk_array_int *wrap_indeces;; - size_t wrap_num; + struct ltk_array_int *wrap_indeces; size_t len; uint16_t font_size; - int x_max; - int x_min; int y_max; int y_min; int w;