commit 16e9709ac835f46a608c339a632806923465e956
parent cd31b2005fde2440d4277709a0c6efb114718822
Author: lumidify <nobody@lumidify.org>
Date: Mon, 11 May 2020 21:22:42 +0200
Calculate number of required lines before rendering
Diffstat:
2 files changed, 46 insertions(+), 27 deletions(-)
diff --git a/textedit_wip.c b/textedit_wip.c
@@ -44,14 +44,14 @@ extern Ltk *ltk_global;
LTK_GAP_BUFFER_INIT_IMPL(uint32, uint32_t)
LTK_GAP_BUFFER_INIT_IMPL(script, hb_script_t)
LTK_GAP_BUFFER_INIT_IMPL(int, int)
-LTK_ARRAY_INIT_IMPL(char_type, FriBidiCharType)
LTK_ARRAY_INIT_IMPL(level, FriBidiLevel)
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 *
ltk_render_text_line(
- LtkTextLine *tl,
+ struct ltk_text_line *tl,
+ int max_width,
Display *dpy,
Window window,
GC gc,
@@ -59,10 +59,31 @@ ltk_render_text_line(
XColor fg,
XColor bg)
{
+ int lines = 0;
+ int cur_x = 0, cur_y = 0;
+ struct ltk_text_run *cur = tl->first_run;
+ do {
+ for (int i = 0; i < cur->num_glyphs; i++) {
+ x = cur_x + cur->glyphs[i]->info->xoff + cur->glyphs[i]->x_offset;
+ if (x > max_width) {
+ int j = 0;
+ for (j = i; j >= 0; j--) {
+ if (glyphs[j]->cluster != glyphs[i]->cluster) {
+ /* must increase one again so the actual
+ next character is used */
+ j++;
+ break;
+ }
+ }
+ i = j;
+ lines++;
+ }
+ }
+ } while (cur = cur->next);
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);
+ XImage *img = XCreateImage(dpy, CopyFromParent, depth, ZPixmap, 0, NULL, max_width, tl->h * lines, 32, 0);
img->data = calloc(img->bytes_per_line, img->height);
XInitImage(img);
int b;
@@ -76,7 +97,7 @@ ltk_render_text_line(
}
}
- LtkTextSegment *ts = tl->start_segment;
+ cur = tl->runs;
int x = 0;
int y = 0;
int is_hor = HB_DIRECTION_IS_HORIZONTAL(ts->dir);
@@ -290,6 +311,7 @@ ltk_text_run_create(size_t start_index, size_t len, hb_script_t script, hb_direc
run->len = len;
run->script = script;
run->dir = dir;
+ run->last = NULL;
run->next = NULL;
}
@@ -323,12 +345,14 @@ ltk_text_line_itemize(struct ltk_text_line *tl) {
if (!first_run) {
first_run = cur_run = new;
} else {
- cur->next = new;
- cur = new;
+ cur_run->next = new;
+ new->last = cur_run;
+ cur_run = new;
}
start_index = end_index;
}
- tl->runs = tl->cur_run = first_run;
+ tl->first_run = tl->cur_run = first_run;
+ tl->last_run = cur_run;
}
static void
@@ -348,7 +372,7 @@ ltk_text_run_shape(LtkTextManager *tm, struct ltk_text_run *tr,
hb_buffer_t *buf;
hb_glyph_info_t *ginf, *gi;
hb_glyph_position_t *gpos, *gp;
- unsigned int num_glyphs = 0;
+ tr->num_glyphs = 0;
buf = hb_buffer_create();
hb_buffer_set_direction(buf, run->dir);
@@ -359,24 +383,23 @@ ltk_text_run_shape(LtkTextManager *tm, struct ltk_text_run *tr,
* this should be level 1 clustering instead of level 0 */
hb_buffer_set_cluster_level(buf, HB_BUFFER_CLUSTER_LEVEL_MONOTONE_CHARACTERS);
hb_shape(font->hb, buf, NULL, 0);
- ginf = hb_buffer_get_glyph_infos(buf, &num_glyphs);
- gpos = hb_buffer_get_glyph_positions(buf, &num_glyphs);
+ ginf = hb_buffer_get_glyph_infos(buf, &tr->num_glyphs);
+ gpos = hb_buffer_get_glyph_positions(buf, &tr->num_glyphs);
float scale = stbtt_ScaleForMappingEmToPixels(&tr->font->info, font_size);
- LtkGlyph *last_glyph = NULL;
int x_min = INT_MAX, x_max = INT_MIN, y_min = INT_MAX, y_max = INT_MIN;
int x_abs = 0, y_abs = 0, x1_abs, y1_abs, x2_abs, y2_abs;
/* magic, do not touch */
- /* FIXME: array instead of linked list */
+ tr->glyphs = malloc(sizeof(LtkGlyph) * num_glyph);
+ if (!tr->glyphs) {
+ (void)fprintf("Cannot allocate space for glyphs.\n");
+ exit(1);
+ }
LtkGlyph *glyph;
- for (int i = 0; i < num_glyphs; i++) {
+ for (int i = 0; i < tr->num_glyphs; i++) {
gi = &ginf[i];
gp = &gpos[i];
- glyph = malloc(sizeof(LtkGlyph));
- if (!glyph) {
- (void)fprintf(stderr, "Cannot allocate glyph.\n");
- exit(1);
- }
+ glyph = tr->glyphs[i];
glyph->cluster = gi->cluster;
glyph->info = ltk_get_glyph_info(tr->font, gi->codepoint, scale, glyph_cache);
glyph->info->refs++;
@@ -385,13 +408,6 @@ ltk_text_run_shape(LtkTextManager *tm, struct ltk_text_run *tr,
glyph->y_offset = (int)(gp->y_offset * scale);
glyph->x_advance = (int)(gp->x_advance * scale);
glyph->y_advance = (int)(gp->y_advance * scale);
- glyph->next = NULL;
- if (i == 0) {
- tr->start_glyph = glyph;
- } else {
- last_glyph->next = glyph;
- }
- last_glyph = glyph;
/* Calculate position in order to determine full size of text segment */
x1_abs = x_abs + glyph->info->xoff + glyph->x_offset;
diff --git a/textedit_wip.h b/textedit_wip.h
@@ -42,8 +42,10 @@ LTK_ARRAY_INIT_DECL(level, FriBidiLevel)
LTK_STACK_INIT_DECL(script, int, hb_script_t, pair_index, script);
struct ltk_text_run {
- struct ltk_glyph *start_glyph;
+ LtkGlyph *glyphs;
+ size_t num_glyphs;
struct ltk_text_run *next;
+ struct ltk_text_run *last;
size_t start_index;
size_t len;
LtkFont *font;
@@ -66,7 +68,8 @@ struct ltk_text_line {
struct ltk_gap_buffer_int *log2vis;
struct ltk_gap_buffer_int *vis2log;
struct ltk_array_level *bidi_levels;
- struct ltk_text_run *runs; /* first node in the linked list of runs */
+ struct ltk_text_run *first_run; /* first node in the linked list of runs */
+ struct ltk_text_run *last_run; /* last node in the linked list of runs */
struct ltk_text_run *cur_run; /* current node in the linked list of runs */
struct ltk_text_line *next; /* next text line in the buffer */
unsigned int height; /* height of the line (including wrapping) */