Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add ligatures support via libatures #1671

Draft
wants to merge 6 commits into
base: master
Choose a base branch
from

Conversation

Guldoman
Copy link
Member

Initial glue code to make use of my libatures library.
This is an alternative to the implementation using harfbuzz in #1659.

The main advantages of using libatures instead of harfbuzz are mainly due to the reduced complexity of the library and increased control.

This also adds configuration support for ligatures, by providing a new entry in the options table of renderer.font.load.

By default ligatures are disabled except for the rvrn, ccmp, rlig and required features.
Enabling ligatures by setting the option ligatures to true will add the calt, liga, clig and dlig features.

It's possible to fully customize the loaded features by setting ligatures to a table which contains the name of the feature as key, and a boolean as value (set to false to disable a "default" feature, true to enable generic features).
For example, setting ligatures = { ss01 = true, ccmp = false } will result in ss01 to be enabled, as well as all the "default" features, except for ccmp.

Closes #66.

@TorchedSammy
Copy link
Contributor

TorchedSammy commented Dec 29, 2023

  • using ss05 with monaspace crashes the editor
  • ligatures should be able to be changed with string values (ligatures = {'ss01', 'ss02'})
  • sometimes it just crashes out of nowhere:
~ 
∆ lite-xl
munmap_chunk(): invalid pointer
~                                                                             
∆ lite-xl
free(): invalid next size (fast)
~ 6s                                                                          
∆ 

@Guldoman
Copy link
Member Author

Should be fixed by

diff --git a/src/api/renderer.c b/src/api/renderer.c
index 81df4c4..84883ca 100644
--- a/src/api/renderer.c
+++ b/src/api/renderer.c
@@ -24,6 +24,18 @@ unsigned char default_ligature_features[][4] = {
 #define n_default_features (sizeof(default_features) / sizeof(default_features[0]))
 #define n_default_ligature_features (sizeof(default_ligature_features) / sizeof(default_ligature_features[0]))
 
+static size_t get_table_size(lua_State *L, int index) {
+  if (index < 0)
+    index = lua_gettop(L) + index + 1;
+  size_t counter = 0;
+  lua_pushnil(L);
+  while (lua_next(L, index) != 0) {
+    counter++;
+    lua_pop(L, 1); // pop value
+  }
+  return counter;
+}
+
 static int font_get_options(
   lua_State *L,
   ERenFontAntialiasing *antialiasing,
@@ -92,7 +104,7 @@ static int font_get_options(
     lua_getfield(L, 3, "ligatures");
     if (lua_istable(L, -1)) {
       liga_options->n_features = 0;
-      size_t n_features = n_default_features + n_default_ligature_features + luaL_len(L, -1);
+      size_t n_features = n_default_features + n_default_ligature_features + get_table_size(L, -1);
       liga_options->features = calloc(n_features, sizeof(unsigned char [4]));
       // Handle default features
       for (size_t i = 0; i < n_default_features; i++) {
@@ -121,7 +133,12 @@ static int font_get_options(
       lua_pushnil(L);
       while (lua_next(L, -2) != 0) {
         size_t taglen;
-        const char* tagname = luaL_checklstring(L, -2, &taglen);
+        const char* tagname;
+        if (lua_isinteger(L, -2)) {
+          tagname = luaL_checklstring(L, -1, &taglen);
+        } else {
+          tagname = luaL_checklstring(L, -2, &taglen);
+        }
         if (taglen != 4) {
           return luaL_error(
             L,
@@ -134,7 +151,6 @@ static int font_get_options(
         }
         lua_pop(L, 1); // pop value
       }
-      lua_pop(L, 1); // pop key
     } else if(lua_toboolean(L, -1)) {
       size_t n_features = n_default_features + n_default_ligature_features;
       liga_options->features = malloc(n_features * sizeof(unsigned char [4]));

This also adds support for specifying features directly, like ligatures = {dlig = false, "ss01", "ss05"}.

I'll push this when I can.

This allows for ligature options in the format:
`ligatures = {dlig = false, "ss01", "ss05"}`
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Ligature Support
2 participants