URI:
       tMess around a bit - ltkx - GUI toolkit for X11 (WIP)
  HTML git clone git://lumidify.org/ltkx.git
   DIR Log
   DIR Files
   DIR Refs
   DIR README
   DIR LICENSE
       ---
   DIR commit bb37974073b00337f90fe044b91240ef893ff374
   DIR parent 17f7c08af649a3bfe395f77a63980d7d1defbce1
  HTML 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(-)
       ---
   DIR diff --git a/text-hb.c b/text-hb.c
       t@@ -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
       t@@ -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;
       t@@ -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]);
       t@@ -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;
       t@@ -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. */
       t@@ -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);
       t@@ -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;
       t@@ -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;
                        }
   DIR diff --git a/text-hb.h b/text-hb.h
       t@@ -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
       t@@ -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;