Skip to content

Commit

Permalink
[WIP]: overhaul text rendering
Browse files Browse the repository at this point in the history
Until now, Eovim was using the Evas_Textgrid to display text. It
consists in a fixed-size grid of codepoints associated with unique
glyphs and render attributes, such as the color and basic shape.

This has several problems, mainly:

- the textgrid has limited attributes support:
  - the color of underlined text is the same as the foreground
  - there is no "undercurl" equivalent
- you cannot specify a 'linespace' (#34)
- support for multiple width character is partial
- you cannot use the opentype capabilities such as ligatures (#44)

It was time for a change to support the above. Eovim now uses
Evas_Textblock, which is low-level rich text widget provided by EFL.
However, it is tricky to use the same way than the Textgrid, but a
proper separation between model/view/controller (wow... so innovative)
actually makes surprisingly it trivial to handle!

Fix #34
Fix #44
  • Loading branch information
Jean Guyomarc'h committed Jun 5, 2020
1 parent 27abdfe commit e4685c7
Show file tree
Hide file tree
Showing 26 changed files with 1,794 additions and 1,679 deletions.
2 changes: 2 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,8 @@ add_executable(eovim
"${SRC_DIR}/event/mode.c"
"${SRC_DIR}/event/cmdline.c"
"${SRC_DIR}/event/eovim.c"
"${SRC_DIR}/event/linegrid.c"
"${SRC_DIR}/event/util.c"
"${SRC_DIR}/nvim_api.c"
"${SRC_DIR}/nvim_attach.c"
"${SRC_DIR}/nvim_completion.c"
Expand Down
2 changes: 1 addition & 1 deletion data/themes/cursor.edc
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ group { "eovim/cursor";
set_color_class("cursor_on", r, g, b, 255);
set_color_class("cursor_dimmed", r, g, b, 40);
set_color_class("cursor_dimmed2", r, g, b, 80);
set_color_class("cursor_full", r, g, b, 255);
//set_color_class("cursor_full", r, g, b, 255);
} else if (id == 2) { /* may blink set */
set_int(g_may_blink, getarg(2));
}
Expand Down
10 changes: 6 additions & 4 deletions data/themes/default.edc
Original file line number Diff line number Diff line change
Expand Up @@ -116,13 +116,15 @@ collections {
color_class: "background";
}
}

swallow { "eovim.main.view";
desc { "default";
rel1.to: "tabs_headings";
rel1.relative: 0.0 1.0;
}
desc { "default";
rel1.to: "eovim.tabline";
rel1.relative: 0.0 1.0;
}
}


/* CAPS LOCK WARNING.
* ------------------------------------------------------------------
*
Expand Down
23 changes: 6 additions & 17 deletions include/eovim/gui.h
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ struct gui
} cmdline;

struct {
char *name; /**< Dynamically allocated */
Eina_Stringshare *name;
unsigned int size;
} font;

Expand All @@ -64,8 +64,6 @@ struct gui

/** True when the caps lock warning is on, False otherwise */
Eina_Bool capslock_warning;

Eina_Bool must_resize;
unsigned int active_tab; /**< Identifier of the active tab */
};

Expand Down Expand Up @@ -130,22 +128,15 @@ void gui_shutdown(void);
Eina_Bool gui_add(s_gui *gui, s_nvim *nvim);
void gui_del(s_gui *gui);
void gui_resize(s_gui *gui, unsigned int cols, unsigned int rows);
void gui_resized_confirm(s_gui *gui, unsigned int cols, unsigned int rows);
void gui_clear(s_gui *gui);
void gui_eol_clear(s_gui *gui);
void gui_put(s_gui *gui, const Eina_Unicode *ustring, unsigned int size);
void gui_cursor_goto(s_gui *gui, unsigned int to_x, unsigned int to_y);
void gui_style_set(s_gui *gui, const s_termview_style *style);
void gui_update_fg(s_gui *gui, t_int color);
void gui_update_bg(s_gui *gui, t_int color);
void gui_update_sp(s_gui *gui, t_int color);
void gui_scroll_region_set(s_gui *gui, int x, int y, int w, int h);
void gui_scroll(s_gui *gui, int scroll);
void gui_busy_set(s_gui *gui, Eina_Bool busy);
void gui_bg_color_set(s_gui *gui, int r, int g, int b, int a);
void gui_config_show(s_gui *gui);
void gui_config_hide(s_gui *gui);
void gui_die(s_gui *gui, const char *fmt, ...) EINA_PRINTF(2, 3);
void gui_default_colors_set(
s_gui *gui,
union color fg,
union color bg,
union color sp);

void gui_completion_prepare(s_gui *gui, size_t items);
void gui_completion_show(s_gui *gui, size_t max_word_len, size_t max_menu_len,
Expand All @@ -156,8 +147,6 @@ void gui_completion_add(s_gui *gui, s_completion *completion);
void gui_completion_selected_set(s_gui *gui, int index);

void gui_bell_ring(s_gui *gui);
void gui_fullscreen_set(s_gui *gui, Eina_Bool fullscreen);
void gui_maximized_set(s_gui *gui, Eina_Bool maximized);

void gui_cmdline_show(s_gui *gui, const char *content,
const char *prompt, const char *firstc);
Expand Down
6 changes: 3 additions & 3 deletions include/eovim/msgpack_helper.h
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,13 @@

/**
* Retrive a map from a msgpack object @a Obj. If @a Obj is not of type map,
* then this macro jumps to the label @a Fail.
* then this macro executes code @p OnFail
*/
#define EOVIM_MSGPACK_MAP_EXTRACT(Obj, Fail) \
#define EOVIM_MSGPACK_MAP_EXTRACT(Obj, OnFail) \
({ \
if (EINA_UNLIKELY((Obj)->type != MSGPACK_OBJECT_MAP)) { \
CRI("A map was expected, but we got 0x%x", (Obj)->type); \
goto Fail; } \
OnFail; } \
&((Obj)->via.map); \
})

Expand Down
10 changes: 4 additions & 6 deletions include/eovim/nvim.h
Original file line number Diff line number Diff line change
Expand Up @@ -51,9 +51,7 @@ struct nvim
msgpack_packer packer;
uint32_t request_id;

void (*hl_group_decode)(s_nvim *, unsigned int, f_highlight_group_decode);

Eina_UStrbuf *decode;
Eina_Hash *modes;
Eina_Bool mouse_enabled;

struct {
Expand All @@ -70,9 +68,6 @@ struct nvim
s_nvim *nvim_new(const s_options *opts, const char *const args[]);
void nvim_free(s_nvim *nvim);
uint32_t nvim_next_uid_get(s_nvim *nvim);
Eina_Bool nvim_api_response_dispatch(s_nvim *nvim, const s_request *req, const msgpack_object_array *args);
Eina_Bool nvim_mode_add(s_nvim *nvim, s_mode *mode);
const s_mode *nvim_named_mode_get(const s_nvim *nvim, Eina_Stringshare *name);
void nvim_mouse_enabled_set(s_nvim *nvim, Eina_Bool enable);
Eina_Bool nvim_mouse_enabled_get(const s_nvim *nvim);
void nvim_attach(s_nvim *nvim);
Expand All @@ -86,4 +81,7 @@ void nvim_attach(s_nvim *nvim);
*/
Eina_Bool nvim_flush(s_nvim *nvim);

struct mode *nvim_mode_new(void);
void nvim_mode_free(struct mode *mode);

#endif /* ! __EOVIM_NVIM_H__ */
9 changes: 7 additions & 2 deletions include/eovim/nvim_event.h
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,14 @@
#include "eovim/types.h"
#include <msgpack.h>

Eina_Bool nvim_event_dispatch(s_nvim *nvim, Eina_Stringshare *method_name,
Eina_Stringshare *command, const msgpack_object_array *args);
struct method;

Eina_Bool nvim_event_init(void);
void nvim_event_shutdown(void);

const struct method *nvim_event_method_find(Eina_Stringshare *method_name);
Eina_Bool nvim_event_method_dispatch(s_nvim *nvim, const struct method *method, Eina_Stringshare *command, const msgpack_object_array *args);

Eina_Bool nvim_event_method_batch_end(s_nvim *nvim, const struct method *method);

#endif /* ! __EOVIM_EVENT_H__ */
23 changes: 0 additions & 23 deletions include/eovim/nvim_helper.h
Original file line number Diff line number Diff line change
Expand Up @@ -5,29 +5,6 @@

#include "eovim/types.h"

typedef struct
{
struct {
uint8_t r;
uint8_t g;
uint8_t b;
Eina_Bool used;
} bg, fg;
} s_hl_group;

typedef void (*f_highlight_group_decode)(s_nvim *nvim, const s_hl_group *hl_group);

void
nvim_helper_highlight_group_decode(s_nvim *nvim,
unsigned int group,
f_highlight_group_decode func);

void
nvim_helper_highlight_group_decode_noop(s_nvim *nvim,
unsigned int group,
f_highlight_group_decode func);


Eina_Bool nvim_helper_autocmd_do(s_nvim *nvim, const char *event, f_nvim_api_cb func, void *func_data);

Eina_Bool nvim_helper_config_reload(s_nvim *nvim);
Expand Down
13 changes: 11 additions & 2 deletions include/eovim/nvim_request.h
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,19 @@
* result of the request. See msgpack-rpc.
* @return EINA_TRUE on success, EINA_FALSE on failure
*
* @note This function is responsible for calling nvim_flush().
* This function is responsible for generating in \p pk the response message
* Pack the message: it is an array of four (4) items:
* - the rpc type:
* - 1 is a request response
* - the unique identifier of the request
* - the error return
* - the result return
* See: https://github.com/msgpack-rpc/msgpack-rpc/blob/master/spec.md
*
* Then, call nvim_flush()
*/
typedef Eina_Bool (*f_nvim_request_cb)(s_nvim *nvim, const msgpack_object_array *args,
msgpack_packer *pk);
msgpack_packer *pk, uint32_t req_id);

Eina_Bool nvim_request_init(void);
void nvim_request_shutdown(void);
Expand Down
72 changes: 41 additions & 31 deletions include/eovim/termview.h
Original file line number Diff line number Diff line change
Expand Up @@ -6,51 +6,61 @@
#include "eovim/types.h"
#include <Evas.h>

typedef struct termview_style s_termview_style;
typedef struct termview_color s_termview_color;

struct termview_color
{
uint8_t r;
uint8_t g;
uint8_t b;
uint8_t a;
};

struct termview_style
{
t_int fg_color;
t_int bg_color;
t_int sp_color;
Eina_Bool reverse;
Eina_Bool italic;
Eina_Bool bold;
Eina_Bool underline;
Eina_Bool undercurl;
union color fg_color;
union color bg_color;
union color sp_color;
Eina_Bool reverse;
Eina_Bool italic;
Eina_Bool bold;
Eina_Bool underline;
Eina_Bool undercurl;
Eina_Bool strikethrough;
};


Eina_Bool termview_init(void);
void termview_shutdown(void);
Evas_Object *termview_add(Evas_Object *parent, s_nvim *nvim);
void termview_resize(Evas_Object *obj, unsigned int cols, unsigned int rows);
void termview_resized_confirm(Evas_Object *obj, unsigned int cols, unsigned int rows);
void termview_font_set(Evas_Object *obj, const char *font_name, unsigned int font_size);
void termview_matrix_set(Evas_Object *obj, unsigned int cols, unsigned int rows);
void termview_cell_size_get(const Evas_Object *obj, unsigned int *w, unsigned int *h);
void termview_size_get(const Evas_Object *obj, unsigned int *cols, unsigned int *rows);
void termview_refresh(Evas_Object *obj);
void termview_clear(Evas_Object *obj);
void termview_eol_clear(Evas_Object *obj);
void termview_put(Evas_Object *obj, const Eina_Unicode *ustring, unsigned int size);
void termview_cursor_goto(Evas_Object *obj, unsigned int to_x, unsigned int to_y);
void termview_style_set(Evas_Object *obj, const s_termview_style *style);
void termview_scroll_region_set(Evas_Object *obj, const Eina_Rectangle *region);
void termview_scroll(Evas_Object *obj, int count);
void termview_fg_color_set(Evas_Object *obj, int r, int g, int b, int a);
void termview_fg_color_get(const Evas_Object *obj, int *r, int *g, int *b, int *a);
s_termview_color termview_color_decompose(uint32_t col);
void termview_cell_to_coords(const Evas_Object *obj, unsigned int cell_x, unsigned int cell_y, int *px, int *py);
void termview_cursor_mode_set(Evas_Object *obj, const s_mode *mode);
void termview_cursor_visibility_set(Evas_Object *obj, Eina_Bool visible);

struct termview_style *termview_style_get(Evas_Object *obj, t_int style_id);

void termview_scroll(
Evas_Object *obj,
int top, int bot, int left, int right, int rows);

void termview_default_colors_set(
Evas_Object *obj,
union color fg,
union color bg,
union color sp);

void termview_font_set(Evas_Object *obj,
Eina_Stringshare *font_name,
unsigned int font_size);

void
termview_line_edit(
Evas_Object *obj,
unsigned int row,
unsigned int col,
const char *text,
size_t text_len,
t_int style_id,
size_t repeat);

void termview_flush(Evas_Object *obj);
void termview_linespace_set( Evas_Object *obj, unsigned int linespace);
void termview_redraw_end(Evas_Object *obj);


#endif /* ! __EOVIM_TERMVIEW_H__ */
30 changes: 26 additions & 4 deletions include/eovim/types.h
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,21 @@ typedef struct geometry s_geometry;
typedef Eina_Bool (*f_event_cb)(s_nvim *nvim, const msgpack_object_array *args);
typedef void (*f_nvim_api_cb)(s_nvim *nvim, void *data, const msgpack_object *result);


#define COLOR_DEFAULT UINT32_C(0)


union color
{
struct {
uint8_t b;
uint8_t g;
uint8_t r;
uint8_t a;
};
uint32_t value;
};

typedef enum
{
CURSOR_SHAPE_BLOCK = 0,
Expand Down Expand Up @@ -55,17 +70,24 @@ struct version
struct mode
{
Eina_Stringshare *name; /**< Name of the mode */
Eina_Stringshare *short_name;
e_cursor_shape cursor_shape; /**< Shape of the cursor */
unsigned int cell_percentage;
/**< Percentage of the cell that the cursor occupies */
unsigned int blinkon; /**< Delay during which the cursor is displayed */
unsigned int blinkoff; /**< Delay during which the cursor is hidden */
unsigned int blinkwait; /**< Delay for transitionning ON <-> OFF */
t_int attr_id;
t_int attr_id_lm;

/* This is still unimplemented by neovim, but we receive it. */
int mouse_shape;

/* These two fields are DEPRECATED and will not be used. They just exist so
* we actually PARSE the messages from neovim without raising any warning,
* but do nothing with it. */
unsigned int hl_id;
unsigned int id_lm;
char short_name[1];
/**< Short name... I don't remember what this is... but it is a string
* embedded at the end of this struct (not just a single char) */
unsigned int hl_lm;
};

#endif /* ! __EOVIM_TYPES_H__ */
2 changes: 1 addition & 1 deletion src/event/cmdline.c
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ nvim_event_cmdline_show(s_nvim *nvim,

/* The map will contain highlight attributes */
//const msgpack_object_map *const map =
// EOVIM_MSGPACK_MAP_EXTRACT(&cont->ptr[0], del_buf);
// EOVIM_MSGPACK_MAP_EXTRACT(&cont->ptr[0], goto del_buf);

/* Extract the content of the command-line */
const msgpack_object *const cont_o = &(cont->ptr[1]);
Expand Down
1 change: 0 additions & 1 deletion src/event/eovim.c
Original file line number Diff line number Diff line change
Expand Up @@ -7,5 +7,4 @@ nvim_event_eovim_reload(
s_nvim *const nvim, const msgpack_object_array *const args EINA_UNUSED)
{
return nvim_helper_config_reload(nvim);
return EINA_TRUE;
}
Loading

0 comments on commit e4685c7

Please sign in to comment.