commit bb37974073b00337f90fe044b91240ef893ff374
parent 17f7c08af649a3bfe395f77a63980d7d1defbce1
Author: lumidify <nobody@lumidify.org>
Date:   Thu, 19 Mar 2020 11:17:49 +0100
Mess around a bit
Well, now "I'm a button" is split into individual characters and the
spaces are gone. Looks beautiful, doesn't it?
Diffstat:
| M | text-hb.c |  |  | 182 | ++++++++++++------------------------------------------------------------------- | 
| M | text-hb.h |  |  | 6 | +++++- | 
2 files changed, 32 insertions(+), 156 deletions(-)
diff --git a/text-hb.c b/text-hb.c
@@ -1,6 +1,6 @@
 /*
  * This file is part of the Lumidify ToolKit (LTK)
- * Copyright (c) 2017, 2018 lumidify <nobody@lumidify.org>
+ * Copyright (c) 2017, 2018, 2020 lumidify <nobody@lumidify.org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a copy
  * of this software and associated documentation files (the "Software"), to deal
@@ -321,8 +321,6 @@ ltk_create_text_line(LtkTextManager *tm, char *text, uint16_t fontid, uint16_t s
 	LtkFont *font;
 	LtkFont *default_font;
 	LtkTextLine *tl = malloc(sizeof(LtkTextLine));
-	tl->w = 0;
-	tl->h = 0;
 	tl->start_segment = NULL;
 	LtkTextSegment *cur_ts = NULL;
 	LtkTextSegment *new_ts = NULL;
@@ -345,8 +343,6 @@ ltk_create_text_line(LtkTextManager *tm, char *text, uint16_t fontid, uint16_t s
 	FriBidiChar *vis_str = malloc(sizeof(FriBidiChar) * ulen);
 	ulen = fribidi_charset_to_unicode(FRIBIDI_CHAR_SET_UTF8, text, strlen(text), log_str);
 	fribidi_log2vis(log_str, ulen, pbase_dir, vis_str, NULL, NULL, NULL);
-	free(log_str);
-	free(pbase_dir);
 
 	hb_unicode_funcs_t *ufuncs = hb_unicode_funcs_get_default();
 	hb_script_t cur_script = hb_unicode_script(ufuncs, vis_str[0]);
@@ -359,7 +355,8 @@ ltk_create_text_line(LtkTextManager *tm, char *text, uint16_t fontid, uint16_t s
 	for (int p = 0; p < ulen; p++) {
 		gid = stbtt_FindGlyphIndex(&font->info, vis_str[p]);
 		cur_script = hb_unicode_script(ufuncs, vis_str[p]);
-		if (!gid || (last_script != cur_script && cur_script != HB_SCRIPT_INHERITED && cur_script != HB_SCRIPT_COMMON)) {
+		//if (!gid || (last_script != cur_script && cur_script != HB_SCRIPT_INHERITED && cur_script != HB_SCRIPT_COMMON)) {
+		if (!gid || (last_script != cur_script && cur_script != HB_SCRIPT_INHERITED && cur_script)) {
 			/* This is extremely efficient... */
 			FcPattern *pat = FcPatternDuplicate(tm->fcpattern);
 			FcPattern *match;
@@ -400,171 +397,44 @@ ltk_create_text_line(LtkTextManager *tm, char *text, uint16_t fontid, uint16_t s
 	cur_ts = new_ts;
 
 	free(vis_str);
+	free(log_str);
+	free(pbase_dir);
 
 	/* calculate width of text line
 	   NOTE: doesn't work with mixed horizontal and vertical text */
 	LtkTextSegment *ts = tl->start_segment;
 	int is_hor = HB_DIRECTION_IS_HORIZONTAL(ts->dir);
+	tl->y_max = tl->x_max = INT_MIN;
+	tl->y_min = tl->x_min = INT_MAX;
+	tl->w = tl->h = 0;
 	while (ts) {
 		if (is_hor) {
-			if (tl->h < ts->h) {
-				tl->h = ts->h;
+			if (tl->y_max < ts->y_max) {
+				tl->y_max = ts->y_max;
+			}
+			if (tl->y_min > ts->y_min) {
+				tl->y_min = ts->y_min;
 			}
 			tl->w += ts->w;
 		} else {
-			if (tl->w < ts->w) {
-				tl->w = ts->w;
+			if (tl->x_max < ts->x_max) {
+				tl->x_max = ts->x_max;
+			}
+			if (tl->x_min > ts->x_min) {
+				tl->x_min = ts->x_min;
 			}
 			tl->h += ts->h;
 		}
 		ts = ts->next;
 	}
-
-	return tl;
-}
-
-#if 0
-LtkTextLine *
-ltk_create_text_line(LtkTextManager *tm, char *text, uint16_t fontid, uint16_t size)
-{
-	size_t pos = 0;
-	size_t last_pos = 0;
-	size_t start_pos = 0;
-	unsigned int len = strlen(text);
-	uint32_t ch;
-	uint32_t gid;
-	LtkFont *font;
-	LtkFont *default_font;
-	LtkTextLine *tl = malloc(sizeof(LtkTextLine));
-	tl->w = 0;
-	tl->h = 0;
-	tl->start_segment = NULL;
-	LtkTextSegment *cur_ts = NULL;
-	LtkTextSegment *new_ts = NULL;
-	uint16_t default_font_id = fontid;
-	uint16_t last_font_id = fontid;
-	uint16_t cur_font_id = fontid;
-	int k = kh_get(fontstruct, tm->font_cache, fontid);
-	font = default_font = kh_value(tm->font_cache, k);
-	int utlen = u8_strlen(text);
-
-	FriBidiChar *us = malloc(sizeof(FriBidiChar) * utlen);
-	int ulen = fribidi_charset_to_unicode(FRIBIDI_CHAR_SET_UTF8, text, len, us);
-
-	uint32_t* tmp_vis = malloc(sizeof(uint32_t) * utlen);
-	FriBidiStrIndex *tmp_pos_log2vis = malloc(sizeof(FriBidiStrIndex) * utlen);
-	FriBidiCharType *tmp_bidi_types = malloc(sizeof(FriBidiCharType) * utlen);
-	FriBidiLevel *tmp_embed_lvls = malloc(sizeof(FriBidiLevel) * utlen);
-	FriBidiJoiningType *tmp_join_types = malloc(sizeof(FriBidiJoiningType) * utlen);
-	FriBidiArabicProp *tmp_ar_props = malloc(sizeof(FriBidiArabicProp) * utlen);
-
-	fribidi_get_bidi_types(us, ulen, tmp_bidi_types);
-	FriBidiParType basedir = FRIBIDI_PAR_LTR;
-	FriBidiLevel resolve_par_dir = fribidi_get_par_embedding_levels(tmp_bidi_types, ulen, &basedir, tmp_embed_lvls);
-	//for (int i = 0; i < utlen; i++) {printf("%d ", tmp_bidi_types[i]);}; printf("\n");
-	fribidi_get_joining_types(us, ulen, tmp_join_types);
-	memcpy(tmp_ar_props, tmp_join_types, ulen * sizeof(FriBidiJoiningType));
-	fribidi_join_arabic(tmp_bidi_types, ulen, tmp_embed_lvls, tmp_ar_props);
-	
-	//fribidi_shape(FRIBIDI_FLAG_SHAPE_MIRRORING | FRIBIDI_FLAG_SHAPE_ARAB_PRES | FRIBIDI_FLAG_SHAPE_ARAB_LIGA, tmp_embed_lvls, ulen, tmp_ar_props, us);
-	fribidi_shape(FRIBIDI_FLAG_SHAPE_MIRRORING, tmp_embed_lvls, ulen, tmp_ar_props, us);
-	for (int i = 0; i < utlen; i++) {
-		printf("%d ", tmp_embed_lvls[i]);
-	}
-	printf("\n");
-
-	memcpy(tmp_vis, us, sizeof(uint32_t) * ulen);
-	for (int i = 0; i < ulen; i++) {
-		tmp_pos_log2vis[i] = i;
-	}
-
-	FriBidiLevel levels = fribidi_reorder_line(FRIBIDI_FLAGS_ARABIC, tmp_bidi_types, ulen, 0, basedir, tmp_embed_lvls, tmp_vis, tmp_pos_log2vis);
-
-	uint32_t *tmp_log = malloc(sizeof(uint32_t) * ulen);
-	size_t inc = 0;
-	for (int i = 0; i < ulen; i++) {
-		tmp_log[i] = u8_nextmemchar(text, &inc);
-	}
-	FriBidiChar *vis = malloc(sizeof(FriBidiChar) * ulen);
-	for (int i = 0; i < ulen; i++) {
-		vis[i] = tmp_log[tmp_pos_log2vis[i]];
-		//printf("%x %x %x\n", vis[i], tmp_vis[i], tmp_log[i]);
-	}
-	/*
-        FriBidiCharType *pbase_dir = malloc(sizeof(FriBidiCharType) * (ulen + 1));
-        for (int i = 0; i < ulen; i++) {
-                pbase_dir[i] = FRIBIDI_TYPE_ON;
-        }
-	fribidi_log2vis(us, ulen, pbase_dir, vis, NULL, NULL, NULL);
-	*/
-	char *tmp_i_have_no_clue = malloc(len + 1);
-	fribidi_charset_to_unicode(FRIBIDI_CHAR_SET_UTF8, text, len, us);
-	fribidi_unicode_to_charset(FRIBIDI_CHAR_SET_UTF8, tmp_vis, ulen, tmp_i_have_no_clue);
-	tmp_i_have_no_clue[len] = '\0';
-	//printf("%s\n", tmp_i_have_no_clue);
-	/* NEED TO CREATE NEW SEGMENT WHEN CHANGING DIR!!!
-	   Never mind - hb is forced into LTR anyways since fribidi already did all that stuff
-	   Need to apply this: https://github.com/simoncozens/sile/issues/76#issuecomment-98496101
-	   Maybe split into runs based on dir or script and start with orig font for each run?
-	*/ 
-	for (int p = 0; p < ulen; p++) {
-		/* no idea why I get so many null characters... */
-		//if (!tmp_vis[p]) continue;
-		/* just pass gid to hb? */
-		gid = stbtt_FindGlyphIndex(&font->info, tmp_vis[p]);
-		if (!gid || (p > 0 && tmp_embed_lvls[p] != tmp_embed_lvls[p-1])) {//(p > 0 && (tmp_bidi_types[p] & FRIBIDI_MASK_RTL) != (tmp_bidi_types[p-1] & FRIBIDI_MASK_RTL))) {
-			printf("%d\n", tmp_bidi_types[p] & FRIBIDI_MASK_RTL);
-			/* This is extremely efficient... */
-			FcPattern *pat = FcPatternDuplicate(tm->fcpattern);
-			FcPattern *match;
-			FcResult result;
-			//FcFontSet *sets[] = {NULL};
-			FcPatternAddBool(pat, FC_SCALABLE, 1);
-			FcConfigSubstitute(NULL, pat, FcMatchPattern);
-			FcDefaultSubstitute(pat);
-			//sets[0] = FcFontSort(NULL, pat, FcTrue, NULL, &result);
-			FcCharSet *cs = FcCharSetCreate();
-			FcCharSetAddChar(cs, tmp_vis[p]);
-			FcPatternAddCharSet(pat, FC_CHARSET, cs);
-			match = FcFontMatch(NULL, pat, &result);
-			//match = FcFontSetMatch(NULL, sets, FcTrue, pat, &result);
-			char *file;// = "/usr/local/share/fonts/AwamiNastaliq-1.101/AwamiNastaliq-Regular.ttf";
-			FcPatternGetString(match, FC_FILE, 0, &file);
-			printf("%s\n", file);
-			last_font_id = cur_font_id;
-			cur_font_id = ltk_get_font(tm, file);
-			k = kh_get(fontstruct, tm->font_cache, cur_font_id);
-			font = kh_value(tm->font_cache, k);
-			FcPatternDestroy(match);
-			FcPatternDestroy(pat);
-			if (p - 1 != start_pos) {
-				new_ts = ltk_create_text_segment(tm, tmp_vis + start_pos, p - start_pos, last_font_id, size);
-				if (!new_ts) continue;
-				new_ts->next = NULL;
-				if (!tl->start_segment) tl->start_segment = new_ts;
-				if (cur_ts) cur_ts->next = new_ts;
-				cur_ts = new_ts;
-				start_pos = p;
-				tl->w += new_ts->w;
-				tl->h += new_ts->h;
-			}
-		}
-		if (p == ulen - 1 && p != start_pos) {
-			printf("%d\n", tmp_bidi_types[p] & FRIBIDI_MASK_RTL);
-			new_ts = ltk_create_text_segment(tm, tmp_vis + start_pos, p - start_pos + 1, cur_font_id, size);
-			if (!new_ts) continue;
-			new_ts->next = NULL;
-			if (!tl->start_segment) tl->start_segment = new_ts;
-			if (cur_ts) cur_ts->next = new_ts;
-			cur_ts = new_ts;
-			tl->w += new_ts->w;
-			tl->h += new_ts->h;
-		}
+	if (is_hor) {
+		tl->h = tl->y_max - tl->y_min;
+	} else {
+		tl->w = tl->x_max - tl->x_min;
 	}
 
 	return tl;
 }
-#endif
 
 /* FIXME: could use unsigned int for fontid and size as long as there is code to check neither of them become too large
    -> in case I want to get rid of uint_16_t, etc. */
@@ -638,10 +508,11 @@ ltk_create_text_segment(LtkTextManager *tm, uint32_t *text, unsigned int len, ui
 	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 */
+	LtkGlyph *glyph;
 	for (int i = 0; i < text_len; i++) {
 		gi = &ginf[i];
 		gp = &gpos[i];
-		LtkGlyph *glyph = malloc(sizeof(LtkGlyph));
+		glyph = malloc(sizeof(LtkGlyph));
 		glyph->info = ltk_get_glyph_info(font, gi->codepoint, scale, glyph_cache);
 		/* FIXME: round instead of just casting */
 		glyph->x_offset = (int)(gp->x_offset * scale);
@@ -678,6 +549,7 @@ ltk_create_text_segment(LtkTextManager *tm, uint32_t *text, unsigned int len, ui
 	   later on after I've positioned the glyphs? Well, I guess I'll figure that out eventually... */
         ts->start_x = -x_min;
         ts->start_y = -y_min;
+	// FIXME: need to somehow save advance so spaces aren't lost
 	ts->w = x_max - x_min;
 	ts->h = y_max - y_min;
 	ts->x_min = x_min;
@@ -757,11 +629,11 @@ ltk_render_text_line(
 	int is_hor = HB_DIRECTION_IS_HORIZONTAL(ts->dir);
 	do {
 		if (is_hor) {
-			y = tl->h - ts->y_max;
+			y = tl->h - tl->y_max;
 			ltk_render_text_segment(ts, x + ts->start_x, y, img, fg);
 			x += ts->w;
 		} else {
-			x = tl->w - ts->x_max;
+			x = tl->w - tl->x_max;
 			ltk_render_text_segment(ts, x, y + ts->start_y, img, fg);
 			y += ts->h;
 		}
diff --git a/text-hb.h b/text-hb.h
@@ -1,6 +1,6 @@
 /*
  * This file is part of the Lumidify ToolKit (LTK)
- * Copyright (c) 2017, 2018 lumidify <nobody@lumidify.org>
+ * Copyright (c) 2017, 2018, 2020 lumidify <nobody@lumidify.org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a copy
  * of this software and associated documentation files (the "Software"), to deal
@@ -88,6 +88,10 @@ typedef struct LtkTextSegment {
 typedef struct {
 	unsigned int w;
 	unsigned int h;
+	int x_max;
+	int x_min;
+	int y_max;
+	int y_min;
 	FriBidiParType dir;
 	LtkTextSegment *start_segment;
 } LtkTextLine;