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:
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;