Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
124 changes: 94 additions & 30 deletions src/gtktsm/gtktsm-terminal.c
Original file line number Diff line number Diff line change
Expand Up @@ -358,7 +358,7 @@ static int create_glyph(struct gtktsm_face *face,
{
PangoLayoutLine *line;
cairo_surface_t *surface;
PangoRectangle rec;
PangoRectangle rec, logical_rec;
cairo_format_t format;
PangoLayout *layout;
cairo_t *cr;
Expand All @@ -381,8 +381,34 @@ static int create_glyph(struct gtktsm_face *face,
break;
}

layout = pango_layout_new(face->ctx);

val = g_ucs4_to_utf8(ch, len, NULL, &ulen, NULL);
if (!val) {
r = -ERANGE;
goto err_layout;
}

/* render one line only */
pango_layout_set_height(layout, 0);
/* no line spacing */
pango_layout_set_spacing(layout, 0);
/* set text to char [+combining-chars] */
pango_layout_set_text(layout, val, ulen);

g_free(val);

cnt = pango_layout_get_line_count(layout);
if (cnt == 0) {
r = -ERANGE;
goto err_layout;
}

line = pango_layout_get_line_readonly(layout, 0);
pango_layout_line_get_pixel_extents(line, &logical_rec, &rec);

glyph->format = c2f(format);
glyph->width = face->width * glyph->cwidth;
glyph->width = (logical_rec.width > face->width) ? face->width * 2 : face->width * glyph->cwidth;
glyph->stride = cairo_format_stride_for_width(format, glyph->width);
glyph->height = face->height;

Expand All @@ -407,31 +433,6 @@ static int create_glyph(struct gtktsm_face *face,
}

pango_cairo_update_context(cr, face->ctx);
layout = pango_layout_new(face->ctx);

val = g_ucs4_to_utf8(ch, len, NULL, &ulen, NULL);
if (!val) {
r = -ERANGE;
goto err_layout;
}

/* render one line only */
pango_layout_set_height(layout, 0);
/* no line spacing */
pango_layout_set_spacing(layout, 0);
/* set text to char [+combining-chars] */
pango_layout_set_text(layout, val, ulen);

g_free(val);

cnt = pango_layout_get_line_count(layout);
if (cnt == 0) {
r = -ERANGE;
goto err_layout;
}

line = pango_layout_get_line_readonly(layout, 0);
pango_layout_line_get_pixel_extents(line, NULL, &rec);

cairo_move_to(cr, -rec.x, face->baseline),
cairo_set_source_rgb(cr, 1.0, 1.0, 1.0);
Expand All @@ -442,14 +443,14 @@ static int create_glyph(struct gtktsm_face *face,
glyph->surface = surface;
return 0;

err_layout:
g_object_unref(layout);
cairo_destroy(cr);
err_surface:
cairo_destroy(cr);
cairo_surface_destroy(surface);
err_buffer:
free(glyph->buffer);
glyph->buffer = NULL;
err_layout:
g_object_unref(layout);
return r;
}

Expand Down Expand Up @@ -945,6 +946,7 @@ static int renderer_draw_cell(struct tsm_screen *screen,
unsigned int posy,
const struct tsm_screen_attr *attr,
tsm_age_t age,
bool overflow_next,
void *data)
{
const struct gtktsm_renderer_ctx *ctx = data;
Expand Down Expand Up @@ -1040,6 +1042,67 @@ static int renderer_draw_cell(struct tsm_screen *screen,
return 0;
}

static int gtktsm_get_overflow(struct gtktsm_renderer_ctx *ctx,
const uint32_t *ch,
size_t len,
bool *overflow_next)
{
PangoLayout *layout;
PangoAttrList *attrlist;
PangoRectangle rec, logical_rec;
PangoLayoutLine *line;
struct gtktsm_face *face = ctx->face_regular;
unsigned int cwidth;
size_t ulen, cnt;
char *val;

cwidth = tsm_ucs4_get_width(*ch);
if (!cwidth)
return -ERANGE;

layout = pango_layout_new(face->ctx);
attrlist = pango_layout_get_attributes(layout);
if (attrlist == NULL) {
attrlist = pango_attr_list_new();
pango_layout_set_attributes(layout, attrlist);
pango_attr_list_unref(attrlist);
}

/* render one line only */
pango_layout_set_height(layout, 0);

/* no line spacing */
pango_layout_set_spacing(layout, 0);

val = tsm_ucs4_to_utf8_alloc(ch, len, &ulen);
if (!val) {
return -ERANGE;
}
pango_layout_set_text(layout, val, ulen);
free(val);

cnt = pango_layout_get_line_count(layout);
if (cnt == 0) {
return -ERANGE;
}

line = pango_layout_get_line_readonly(layout, 0);

pango_layout_line_get_pixel_extents(line, &logical_rec, &rec);

*overflow_next = (cwidth < 2) && (logical_rec.width > face->width);

return 0;
}

static int renderer_get_overflow(const uint32_t *ch,
size_t len,
bool *overflow_next,
void *data)
{
return gtktsm_get_overflow(data, ch, len, overflow_next);
}

static void gtktsm_renderer_draw(const struct gtktsm_renderer_ctx *ctx)
{
struct gtktsm_renderer *rend = ctx->rend;
Expand All @@ -1054,6 +1117,7 @@ static void gtktsm_renderer_draw(const struct gtktsm_renderer_ctx *ctx)
cairo_surface_flush(rend->surface);
rend->age = tsm_screen_draw(ctx->screen,
renderer_draw_cell,
renderer_get_overflow,
(void*)ctx);
cairo_surface_mark_dirty(rend->surface);

Expand Down
8 changes: 7 additions & 1 deletion src/tsm/libtsm.h
Original file line number Diff line number Diff line change
Expand Up @@ -181,6 +181,12 @@ typedef int (*tsm_screen_draw_cb) (struct tsm_screen *con,
unsigned int posy,
const struct tsm_screen_attr *attr,
tsm_age_t age,
bool overflow_next,
void *data);

typedef int (*tsm_screen_overflow_cb) (const uint32_t *ch,
size_t len,
bool *overflow_next,
void *data);

int tsm_screen_new(struct tsm_screen **out, tsm_log_t log, void *log_data);
Expand Down Expand Up @@ -263,7 +269,7 @@ void tsm_screen_selection_target(struct tsm_screen *con,
int tsm_screen_selection_copy(struct tsm_screen *con, char **out);

tsm_age_t tsm_screen_draw(struct tsm_screen *con, tsm_screen_draw_cb draw_cb,
void *data);
tsm_screen_overflow_cb overflow_cb, void *data);

/** @} */

Expand Down
15 changes: 12 additions & 3 deletions src/tsm/tsm-render.c
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@

SHL_EXPORT
tsm_age_t tsm_screen_draw(struct tsm_screen *con, tsm_screen_draw_cb draw_cb,
void *data)
tsm_screen_overflow_cb overflow_cb, void *data)
{
unsigned int cur_x, cur_y;
unsigned int i, j, k;
Expand All @@ -57,6 +57,7 @@ tsm_age_t tsm_screen_draw(struct tsm_screen *con, tsm_screen_draw_cb draw_cb,
bool in_sel = false, sel_start = false, sel_end = false;
bool was_sel = false;
tsm_age_t age;
bool overflow_next = false;

if (!con || !draw_cb)
return 0;
Expand Down Expand Up @@ -176,10 +177,18 @@ tsm_age_t tsm_screen_draw(struct tsm_screen *con, tsm_screen_draw_cb draw_cb,
id |= 1ULL << (TSM_UCS4_MAX_BITS + 4);

ch = tsm_symbol_get(con->sym_table, &cell->ch, &len);
if (cell->ch == 0 || (cell->ch == ' ' && !attr.underline))
if (cell->ch == 0 || (cell->ch == ' ' && !attr.underline)) {
len = 0;
if (overflow_next) {
overflow_next = false;
continue;
}
} else {
ret = overflow_cb(ch, len, &overflow_next, data);
}

ret = draw_cb(con, id, ch, len, cell->width,
j, i, &attr, age, data);
j, i, &attr, age, overflow_next, data);
if (ret && warned++ < 3) {
llog_debug(con,
"cannot draw glyph at %ux%u via text-renderer",
Expand Down
Loading