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;