ltkx

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

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:
Mtext-hb.c | 182++++++++++++-------------------------------------------------------------------
Mtext-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;