tCalculate absolute positions of glyphs correctly - 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 b7cef33142db6ea0ca0df918b86eae9c282b6230
DIR parent 48e6e0b3b9804877d23cf36c1390352115340689
HTML Author: lumidify <nobody@lumidify.org>
Date: Wed, 13 May 2020 16:47:39 +0200
Calculate absolute positions of glyphs correctly
Diffstat:
M text-hb.c | 5 +++++
M textedit_wip.c | 91 +++++++++++++------------------
M textedit_wip.h | 14 +++-----------
3 files changed, 46 insertions(+), 64 deletions(-)
---
DIR diff --git a/text-hb.c b/text-hb.c
t@@ -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;
t@@ -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;
t@@ -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;
DIR diff --git a/textedit_wip.c b/textedit_wip.c
t@@ -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;
t@@ -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;
}
}
t@@ -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;
t@@ -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;
t@@ -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;
t@@ -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++;
}
t@@ -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;
t@@ -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;
}
}
t@@ -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;
DIR diff --git a/textedit_wip.h b/textedit_wip.h
t@@ -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;
}
t@@ -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;