[Dev-luatex] [PATCH] luaharfbuzz: Provide interface for variable fonts

Marcel Fabian Kr├╝ger tex at 2krueger.de
Mon Aug 2 18:56:28 CEST 2021


Hi,

please consider the attached patch for luahbtex. It adds a Lua interface
for HarfBuzz's functions around variable fonts.

It is an adoption of recent upstream luaharfbuzz changes with additional
LuaJIT support. While corresponding busted tests are included too, the
font needed to actually run these tests has not been added to the fonts
directory since sending binary files in diffs via email is problematic
and I don't think that anyone is running these tests from the LuaTeX
repo anyway.

Best regards,
Marcel
-------------- next part --------------
>From d43d2306d14414810240c4acc6f5980400ad1c19 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Marcel=20Fabian=20Kr=C3=BCger?= <tex at 2krueger.de>
Date: Mon, 2 Aug 2021 03:01:24 +0200
Subject: [PATCH 1/2] Add interface for font variations in luaharfbuzz

---
 source/texk/web2c/Makefile.in                 |  39 +++-
 source/texk/web2c/luatexdir/am/luaharfbuzz.am |   3 +-
 .../luaharfbuzz/luaharfbuzz-1.1.0-1.rockspec  |   1 +
 .../luaharfbuzz/luaharfbuzz-scm-1.rockspec    |   1 +
 .../luaharfbuzz/spec/harfbuzz_spec.lua        | 116 ++++++++++-
 .../luaharfbuzz/src/luaharfbuzz/face.c        | 195 ++++++++++++++++++
 .../luaharfbuzz/src/luaharfbuzz/font.c        |  61 ++++++
 .../luaharfbuzz/src/luaharfbuzz/luaharfbuzz.c |   3 +
 .../luaharfbuzz/src/luaharfbuzz/luaharfbuzz.h |   2 +
 .../luaharfbuzz/src/luaharfbuzz/variation.c   |  82 ++++++++
 10 files changed, 498 insertions(+), 5 deletions(-)
 create mode 100644 source/texk/web2c/luatexdir/luaharfbuzz/src/luaharfbuzz/variation.c

diff --git a/source/texk/web2c/Makefile.in b/source/texk/web2c/Makefile.in
index 0542d8baf..b3c0de885 100644
--- a/source/texk/web2c/Makefile.in
+++ b/source/texk/web2c/Makefile.in
@@ -595,7 +595,8 @@ am_libluaharfbuzz_a_OBJECTS = luatexdir/luaharfbuzz/src/luaharfbuzz/libluaharfbu
 	luatexdir/luaharfbuzz/src/luaharfbuzz/libluaharfbuzz_a-ot.$(OBJEXT) \
 	luatexdir/luaharfbuzz/src/luaharfbuzz/libluaharfbuzz_a-script.$(OBJEXT) \
 	luatexdir/luaharfbuzz/src/luaharfbuzz/libluaharfbuzz_a-tag.$(OBJEXT) \
-	luatexdir/luaharfbuzz/src/luaharfbuzz/libluaharfbuzz_a-unicode.$(OBJEXT)
+	luatexdir/luaharfbuzz/src/luaharfbuzz/libluaharfbuzz_a-unicode.$(OBJEXT) \
+	luatexdir/luaharfbuzz/src/luaharfbuzz/libluaharfbuzz_a-variation.$(OBJEXT)
 libluaharfbuzz_a_OBJECTS = $(am_libluaharfbuzz_a_OBJECTS)
 libluahbtexspecific_a_AR = $(AR) $(ARFLAGS)
 libluahbtexspecific_a_LIBADD =
@@ -620,7 +621,8 @@ am__objects_3 = luatexdir/luaharfbuzz/src/luaharfbuzz/libluajitharfbuzz_a-blob.$
 	luatexdir/luaharfbuzz/src/luaharfbuzz/libluajitharfbuzz_a-ot.$(OBJEXT) \
 	luatexdir/luaharfbuzz/src/luaharfbuzz/libluajitharfbuzz_a-script.$(OBJEXT) \
 	luatexdir/luaharfbuzz/src/luaharfbuzz/libluajitharfbuzz_a-tag.$(OBJEXT) \
-	luatexdir/luaharfbuzz/src/luaharfbuzz/libluajitharfbuzz_a-unicode.$(OBJEXT)
+	luatexdir/luaharfbuzz/src/luaharfbuzz/libluajitharfbuzz_a-unicode.$(OBJEXT) \
+	luatexdir/luaharfbuzz/src/luaharfbuzz/libluajitharfbuzz_a-variation.$(OBJEXT)
 am_libluajitharfbuzz_a_OBJECTS = $(am__objects_3)
 libluajitharfbuzz_a_OBJECTS = $(am_libluajitharfbuzz_a_OBJECTS)
 libluajithbtexspecific_a_AR = $(AR) $(ARFLAGS)
@@ -1891,6 +1893,7 @@ am__depfiles_remade = ./$(DEPDIR)/aleph-aleph-pool.Po \
 	luatexdir/luaharfbuzz/src/luaharfbuzz/$(DEPDIR)/libluaharfbuzz_a-script.Po \
 	luatexdir/luaharfbuzz/src/luaharfbuzz/$(DEPDIR)/libluaharfbuzz_a-tag.Po \
 	luatexdir/luaharfbuzz/src/luaharfbuzz/$(DEPDIR)/libluaharfbuzz_a-unicode.Po \
+	luatexdir/luaharfbuzz/src/luaharfbuzz/$(DEPDIR)/libluaharfbuzz_a-variation.Po \
 	luatexdir/luaharfbuzz/src/luaharfbuzz/$(DEPDIR)/libluajitharfbuzz_a-blob.Po \
 	luatexdir/luaharfbuzz/src/luaharfbuzz/$(DEPDIR)/libluajitharfbuzz_a-buffer.Po \
 	luatexdir/luaharfbuzz/src/luaharfbuzz/$(DEPDIR)/libluajitharfbuzz_a-class_utils.Po \
@@ -1904,6 +1907,7 @@ am__depfiles_remade = ./$(DEPDIR)/aleph-aleph-pool.Po \
 	luatexdir/luaharfbuzz/src/luaharfbuzz/$(DEPDIR)/libluajitharfbuzz_a-script.Po \
 	luatexdir/luaharfbuzz/src/luaharfbuzz/$(DEPDIR)/libluajitharfbuzz_a-tag.Po \
 	luatexdir/luaharfbuzz/src/luaharfbuzz/$(DEPDIR)/libluajitharfbuzz_a-unicode.Po \
+	luatexdir/luaharfbuzz/src/luaharfbuzz/$(DEPDIR)/libluajitharfbuzz_a-variation.Po \
 	luatexdir/luamd5/$(DEPDIR)/libluajitmisc_a-md5.Po \
 	luatexdir/luamd5/$(DEPDIR)/libluajitmisc_a-md5lib.Po \
 	luatexdir/luamd5/$(DEPDIR)/libluamisc_a-md5.Po \
@@ -4725,7 +4729,8 @@ libluaharfbuzz_a_SOURCES = \
 	luatexdir/luaharfbuzz/src/luaharfbuzz/ot.c \
 	luatexdir/luaharfbuzz/src/luaharfbuzz/script.c \
 	luatexdir/luaharfbuzz/src/luaharfbuzz/tag.c \
-	luatexdir/luaharfbuzz/src/luaharfbuzz/unicode.c
+	luatexdir/luaharfbuzz/src/luaharfbuzz/unicode.c \
+	luatexdir/luaharfbuzz/src/luaharfbuzz/variation.c
 
 libluajitharfbuzz_a_SOURCES = $(libluaharfbuzz_a_SOURCES)
 
@@ -8728,6 +8733,20 @@ luatexdir/luaharfbuzz/src/luaharfbuzz/libluaharfbuzz_a-unicode.obj: luatexdir/lu
 @AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
 @am__fastdepCC_FALSE@	$(AM_V_CC at am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libluaharfbuzz_a_CPPFLAGS) $(CPPFLAGS) $(libluaharfbuzz_a_CFLAGS) $(CFLAGS) -c -o luatexdir/luaharfbuzz/src/luaharfbuzz/libluaharfbuzz_a-unicode.obj `if test -f 'luatexdir/luaharfbuzz/src/luaharfbuzz/unicode.c'; then $(CYGPATH_W) 'luatexdir/luaharfbuzz/src/luaharfbuzz/unicode.c'; else $(CYGPATH_W) '$(srcdir)/luatexdir/luaharfbuzz/src/luaharfbuzz/unicode.c'; fi`
 
+luatexdir/luaharfbuzz/src/luaharfbuzz/libluaharfbuzz_a-variation.o: luatexdir/luaharfbuzz/src/luaharfbuzz/variation.c
+ at am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libluaharfbuzz_a_CPPFLAGS) $(CPPFLAGS) $(libluaharfbuzz_a_CFLAGS) $(CFLAGS) -MT luatexdir/luaharfbuzz/src/luaharfbuzz/libluaharfbuzz_a-variation.o -MD -MP -MF luatexdir/luaharfbuzz/src/luaharfbuzz/$(DEPDIR)/libluaharfbuzz_a-variation.Tpo -c -o luatexdir/luaharfbuzz/src/luaharfbuzz/libluaharfbuzz_a-variation.o `test -f 'luatexdir/luaharfbuzz/src/luaharfbuzz/variation.c' || echo '$(srcdir)/'`luatexdir/luaharfbuzz/src/luaharfbuzz/variation.c
+ at am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) luatexdir/luaharfbuzz/src/luaharfbuzz/$(DEPDIR)/libluaharfbuzz_a-variation.Tpo luatexdir/luaharfbuzz/src/luaharfbuzz/$(DEPDIR)/libluaharfbuzz_a-variation.Po
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='luatexdir/luaharfbuzz/src/luaharfbuzz/variation.c' object='luatexdir/luaharfbuzz/src/luaharfbuzz/libluaharfbuzz_a-variation.o' libtool=no @AMDEPBACKSLASH@
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+ at am__fastdepCC_FALSE@	$(AM_V_CC at am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libluaharfbuzz_a_CPPFLAGS) $(CPPFLAGS) $(libluaharfbuzz_a_CFLAGS) $(CFLAGS) -c -o luatexdir/luaharfbuzz/src/luaharfbuzz/libluaharfbuzz_a-variation.o `test -f 'luatexdir/luaharfbuzz/src/luaharfbuzz/variation.c' || echo '$(srcdir)/'`luatexdir/luaharfbuzz/src/luaharfbuzz/variation.c
+
+luatexdir/luaharfbuzz/src/luaharfbuzz/libluaharfbuzz_a-variation.obj: luatexdir/luaharfbuzz/src/luaharfbuzz/variation.c
+ at am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libluaharfbuzz_a_CPPFLAGS) $(CPPFLAGS) $(libluaharfbuzz_a_CFLAGS) $(CFLAGS) -MT luatexdir/luaharfbuzz/src/luaharfbuzz/libluaharfbuzz_a-variation.obj -MD -MP -MF luatexdir/luaharfbuzz/src/luaharfbuzz/$(DEPDIR)/libluaharfbuzz_a-variation.Tpo -c -o luatexdir/luaharfbuzz/src/luaharfbuzz/libluaharfbuzz_a-variation.obj `if test -f 'luatexdir/luaharfbuzz/src/luaharfbuzz/variation.c'; then $(CYGPATH_W) 'luatexdir/luaharfbuzz/src/luaharfbuzz/variation.c'; else $(CYGPATH_W) '$(srcdir)/luatexdir/luaharfbuzz/src/luaharfbuzz/variation.c'; fi`
+ at am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) luatexdir/luaharfbuzz/src/luaharfbuzz/$(DEPDIR)/libluaharfbuzz_a-variation.Tpo luatexdir/luaharfbuzz/src/luaharfbuzz/$(DEPDIR)/libluaharfbuzz_a-variation.Po
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='luatexdir/luaharfbuzz/src/luaharfbuzz/variation.c' object='luatexdir/luaharfbuzz/src/luaharfbuzz/libluaharfbuzz_a-variation.obj' libtool=no @AMDEPBACKSLASH@
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+ at am__fastdepCC_FALSE@	$(AM_V_CC at am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libluaharfbuzz_a_CPPFLAGS) $(CPPFLAGS) $(libluaharfbuzz_a_CFLAGS) $(CFLAGS) -c -o luatexdir/luaharfbuzz/src/luaharfbuzz/libluaharfbuzz_a-variation.obj `if test -f 'luatexdir/luaharfbuzz/src/luaharfbuzz/variation.c'; then $(CYGPATH_W) 'luatexdir/luaharfbuzz/src/luaharfbuzz/variation.c'; else $(CYGPATH_W) '$(srcdir)/luatexdir/luaharfbuzz/src/luaharfbuzz/variation.c'; fi`
+
 libluahbtexspecific_a-utils-hb.o: utils-hb.c
 @am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libluahbtexspecific_a_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libluahbtexspecific_a-utils-hb.o -MD -MP -MF $(DEPDIR)/libluahbtexspecific_a-utils-hb.Tpo -c -o libluahbtexspecific_a-utils-hb.o `test -f 'utils-hb.c' || echo '$(srcdir)/'`utils-hb.c
 @am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/libluahbtexspecific_a-utils-hb.Tpo $(DEPDIR)/libluahbtexspecific_a-utils-hb.Po
@@ -8966,6 +8985,20 @@ luatexdir/luaharfbuzz/src/luaharfbuzz/libluajitharfbuzz_a-unicode.obj: luatexdir
 @AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
 @am__fastdepCC_FALSE@	$(AM_V_CC at am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libluajitharfbuzz_a_CPPFLAGS) $(CPPFLAGS) $(libluajitharfbuzz_a_CFLAGS) $(CFLAGS) -c -o luatexdir/luaharfbuzz/src/luaharfbuzz/libluajitharfbuzz_a-unicode.obj `if test -f 'luatexdir/luaharfbuzz/src/luaharfbuzz/unicode.c'; then $(CYGPATH_W) 'luatexdir/luaharfbuzz/src/luaharfbuzz/unicode.c'; else $(CYGPATH_W) '$(srcdir)/luatexdir/luaharfbuzz/src/luaharfbuzz/unicode.c'; fi`
 
+luatexdir/luaharfbuzz/src/luaharfbuzz/libluajitharfbuzz_a-variation.o: luatexdir/luaharfbuzz/src/luaharfbuzz/variation.c
+ at am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libluajitharfbuzz_a_CPPFLAGS) $(CPPFLAGS) $(libluajitharfbuzz_a_CFLAGS) $(CFLAGS) -MT luatexdir/luaharfbuzz/src/luaharfbuzz/libluajitharfbuzz_a-variation.o -MD -MP -MF luatexdir/luaharfbuzz/src/luaharfbuzz/$(DEPDIR)/libluajitharfbuzz_a-variation.Tpo -c -o luatexdir/luaharfbuzz/src/luaharfbuzz/libluajitharfbuzz_a-variation.o `test -f 'luatexdir/luaharfbuzz/src/luaharfbuzz/variation.c' || echo '$(srcdir)/'`luatexdir/luaharfbuzz/src/luaharfbuzz/variation.c
+ at am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) luatexdir/luaharfbuzz/src/luaharfbuzz/$(DEPDIR)/libluajitharfbuzz_a-variation.Tpo luatexdir/luaharfbuzz/src/luaharfbuzz/$(DEPDIR)/libluajitharfbuzz_a-variation.Po
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='luatexdir/luaharfbuzz/src/luaharfbuzz/variation.c' object='luatexdir/luaharfbuzz/src/luaharfbuzz/libluajitharfbuzz_a-variation.o' libtool=no @AMDEPBACKSLASH@
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+ at am__fastdepCC_FALSE@	$(AM_V_CC at am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libluajitharfbuzz_a_CPPFLAGS) $(CPPFLAGS) $(libluajitharfbuzz_a_CFLAGS) $(CFLAGS) -c -o luatexdir/luaharfbuzz/src/luaharfbuzz/libluajitharfbuzz_a-variation.o `test -f 'luatexdir/luaharfbuzz/src/luaharfbuzz/variation.c' || echo '$(srcdir)/'`luatexdir/luaharfbuzz/src/luaharfbuzz/variation.c
+
+luatexdir/luaharfbuzz/src/luaharfbuzz/libluajitharfbuzz_a-variation.obj: luatexdir/luaharfbuzz/src/luaharfbuzz/variation.c
+ at am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libluajitharfbuzz_a_CPPFLAGS) $(CPPFLAGS) $(libluajitharfbuzz_a_CFLAGS) $(CFLAGS) -MT luatexdir/luaharfbuzz/src/luaharfbuzz/libluajitharfbuzz_a-variation.obj -MD -MP -MF luatexdir/luaharfbuzz/src/luaharfbuzz/$(DEPDIR)/libluajitharfbuzz_a-variation.Tpo -c -o luatexdir/luaharfbuzz/src/luaharfbuzz/libluajitharfbuzz_a-variation.obj `if test -f 'luatexdir/luaharfbuzz/src/luaharfbuzz/variation.c'; then $(CYGPATH_W) 'luatexdir/luaharfbuzz/src/luaharfbuzz/variation.c'; else $(CYGPATH_W) '$(srcdir)/luatexdir/luaharfbuzz/src/luaharfbuzz/variation.c'; fi`
+ at am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) luatexdir/luaharfbuzz/src/luaharfbuzz/$(DEPDIR)/libluajitharfbuzz_a-variation.Tpo luatexdir/luaharfbuzz/src/luaharfbuzz/$(DEPDIR)/libluajitharfbuzz_a-variation.Po
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='luatexdir/luaharfbuzz/src/luaharfbuzz/variation.c' object='luatexdir/luaharfbuzz/src/luaharfbuzz/libluajitharfbuzz_a-variation.obj' libtool=no @AMDEPBACKSLASH@
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+ at am__fastdepCC_FALSE@	$(AM_V_CC at am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libluajitharfbuzz_a_CPPFLAGS) $(CPPFLAGS) $(libluajitharfbuzz_a_CFLAGS) $(CFLAGS) -c -o luatexdir/luaharfbuzz/src/luaharfbuzz/libluajitharfbuzz_a-variation.obj `if test -f 'luatexdir/luaharfbuzz/src/luaharfbuzz/variation.c'; then $(CYGPATH_W) 'luatexdir/luaharfbuzz/src/luaharfbuzz/variation.c'; else $(CYGPATH_W) '$(srcdir)/luatexdir/luaharfbuzz/src/luaharfbuzz/variation.c'; fi`
+
 libluajithbtexspecific_a-utils-hb.o: utils-hb.c
 @am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libluajithbtexspecific_a_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libluajithbtexspecific_a-utils-hb.o -MD -MP -MF $(DEPDIR)/libluajithbtexspecific_a-utils-hb.Tpo -c -o libluajithbtexspecific_a-utils-hb.o `test -f 'utils-hb.c' || echo '$(srcdir)/'`utils-hb.c
 @am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/libluajithbtexspecific_a-utils-hb.Tpo $(DEPDIR)/libluajithbtexspecific_a-utils-hb.Po
diff --git a/source/texk/web2c/luatexdir/am/luaharfbuzz.am b/source/texk/web2c/luatexdir/am/luaharfbuzz.am
index 1b6187eaa..f98dc79a0 100644
--- a/source/texk/web2c/luatexdir/am/luaharfbuzz.am
+++ b/source/texk/web2c/luatexdir/am/luaharfbuzz.am
@@ -35,7 +35,8 @@ libluaharfbuzz_a_SOURCES = \
 	luatexdir/luaharfbuzz/src/luaharfbuzz/ot.c \
 	luatexdir/luaharfbuzz/src/luaharfbuzz/script.c \
 	luatexdir/luaharfbuzz/src/luaharfbuzz/tag.c \
-	luatexdir/luaharfbuzz/src/luaharfbuzz/unicode.c
+	luatexdir/luaharfbuzz/src/luaharfbuzz/unicode.c \
+	luatexdir/luaharfbuzz/src/luaharfbuzz/variation.c
 
 libluajitharfbuzz_a_SOURCES = $(libluaharfbuzz_a_SOURCES)
 
diff --git a/source/texk/web2c/luatexdir/luaharfbuzz/luaharfbuzz-1.1.0-1.rockspec b/source/texk/web2c/luatexdir/luaharfbuzz/luaharfbuzz-1.1.0-1.rockspec
index 17a84532b..987e9748f 100644
--- a/source/texk/web2c/luatexdir/luaharfbuzz/luaharfbuzz-1.1.0-1.rockspec
+++ b/source/texk/web2c/luatexdir/luaharfbuzz/luaharfbuzz-1.1.0-1.rockspec
@@ -31,6 +31,7 @@ build = {
       "src/luaharfbuzz/script.c",
       "src/luaharfbuzz/direction.c",
       "src/luaharfbuzz/language.c",
+      "src/luaharfbuzz/variation.c",
       "src/luaharfbuzz/class_utils.c"
       },
       libraries = {"harfbuzz"},
diff --git a/source/texk/web2c/luatexdir/luaharfbuzz/luaharfbuzz-scm-1.rockspec b/source/texk/web2c/luatexdir/luaharfbuzz/luaharfbuzz-scm-1.rockspec
index 31ae2ab4f..0f0dd8d33 100644
--- a/source/texk/web2c/luatexdir/luaharfbuzz/luaharfbuzz-scm-1.rockspec
+++ b/source/texk/web2c/luatexdir/luaharfbuzz/luaharfbuzz-scm-1.rockspec
@@ -33,6 +33,7 @@ build = {
       "src/luaharfbuzz/script.c",
       "src/luaharfbuzz/direction.c",
       "src/luaharfbuzz/language.c",
+      "src/luaharfbuzz/variation.c",
       "src/luaharfbuzz/class_utils.c"
       },
       libraries = {"harfbuzz"},
diff --git a/source/texk/web2c/luatexdir/luaharfbuzz/spec/harfbuzz_spec.lua b/source/texk/web2c/luatexdir/luaharfbuzz/spec/harfbuzz_spec.lua
index dfae07d8e..38794372f 100644
--- a/source/texk/web2c/luatexdir/luaharfbuzz/spec/harfbuzz_spec.lua
+++ b/source/texk/web2c/luatexdir/luaharfbuzz/spec/harfbuzz_spec.lua
@@ -230,6 +230,64 @@ describe("harfbuzz module", function()
       assert.True(r)
       assert.are_same(13, i)
     end)
+
+    it("can return variation axes", function()
+      local f = harfbuzz.Face.new('fonts/STIXTwoText[wght].ttf')
+
+      assert.is_same(true, f:ot_var_has_data())
+      local axes = f:ot_var_get_axis_infos()
+      assert.are_same(1, #axes)
+      assert.are_same(harfbuzz.Tag.new("wght"), axes[1].tag)
+      assert.are_same(1, axes[1].axis_index)
+      assert.are_same(400, axes[1].min_value)
+      assert.are_same(400, axes[1].default_value)
+      assert.are_same(700, axes[1].max_value)
+      assert.are_same(0, axes[1].flags)
+      assert.are_same("Weight", f:get_name(axes[1].name_id))
+    end)
+
+    it("can find variation axis", function()
+      local f = harfbuzz.Face.new('fonts/STIXTwoText[wght].ttf')
+
+      local axis = f:ot_var_find_axis_info(harfbuzz.Tag.new("wght"))
+      assert.is_not_nil(axis)
+      assert.are_same(harfbuzz.Tag.new("wght"), axis.tag)
+      assert.are_same(1, axis.axis_index)
+      assert.are_same(400, axis.min_value)
+      assert.are_same(400, axis.default_value)
+      assert.are_same(700, axis.max_value)
+      assert.are_same(0, axis.flags)
+      assert.are_same("Weight", f:get_name(axis.name_id))
+    end)
+
+    it("can return named instances", function()
+      local f = harfbuzz.Face.new('fonts/STIXTwoText[wght].ttf')
+
+      local instances = f:ot_var_named_instance_get_infos()
+      assert.are_same(4, #instances)
+      assert.are_same(3, instances[3].index)
+      assert.are_same("SemiBold", f:get_name(instances[3].subfamily_name_id))
+      assert.are_same(nil, f:get_name(instances[3].postscript_name_id))
+      assert.are_same(600, f:ot_var_named_instance_get_design_coords(3))
+    end)
+
+    it("can normalize variations", function()
+      local f = harfbuzz.Face.new('fonts/STIXTwoText[wght].ttf')
+
+      local normalized, after = f:ot_var_normalize_variations(harfbuzz.Variation.new("wght=400"))
+      assert.is_nil(after)
+      assert.are_same(0, normalized)
+
+      normalized = f:ot_var_normalize_variations(harfbuzz.Variation.new("wght=700"))
+      assert.are_same(1<<14, normalized)
+
+      normalized, after = f:ot_var_normalize_coords(700)
+      assert.is_nil(after)
+      assert.are_same(1<<14, normalized)
+
+      normalized = f:ot_var_normalize_coords(400)
+      assert.are_same(0, normalized)
+    end)
   end)
 
   describe("harfbuzz.Font", function()
@@ -318,6 +376,25 @@ describe("harfbuzz module", function()
       assert.are_same(2857,f:ot_color_glyph_get_png(2):get_length())
       assert.are_same("\137PNG",f:ot_color_glyph_get_png(2):get_data():sub(1, 4))
     end)
+
+    it("can set variations", function()
+      local f = harfbuzz.Font.new(harfbuzz.Face.new('fonts/STIXTwoText[wght].ttf'))
+
+      f:set_variations(harfbuzz.Variation.new("wght=500"))
+      local normalized, after = f:get_var_coords_normalized()
+      assert.is_nil(after)
+      assert.are_same(5174, normalized)
+
+      f:set_var_coords_design(600)
+      local normalized, after = f:get_var_coords_normalized()
+      assert.is_nil(after)
+      assert.are_same(10348, normalized)
+
+      f:set_var_coords_normalized(1<<13)
+      local normalized, after = f:get_var_coords_normalized()
+      assert.is_nil(after)
+      assert.are_same(1<<13, normalized)
+    end)
   end)
 
   describe("harfbuzz.Feature", function()
@@ -339,7 +416,6 @@ describe("harfbuzz module", function()
 
     it("has visible fields", function()
       local f = harfbuzz.Feature.new('-kern')
-      print(getmetatable(f).__index)
       assert.are_equal(tostring(f.tag), 'kern')
       assert.are_equal(f.value, 0)
       assert.are_equal(f.start, nil)
@@ -362,6 +438,44 @@ describe("harfbuzz module", function()
     end)
   end)
 
+  describe("harfbuzz.Variation", function()
+    it("can be initialised with a valid variation string", function()
+      harfbuzz.Variation.new('wght=default')
+      harfbuzz.Variation.new('wght=400')
+      harfbuzz.Variation.new('wght=-20')
+    end)
+
+    it("throws an error when trying to initialise a new variation with an invalid string", function()
+       assert.are_equal(nil, harfbuzz.Variation.new(''))
+       assert.are_equal(nil, harfbuzz.Variation.new('wght'))
+    end)
+
+    it("has a valid tostring value", function()
+      local vs = 'wght=200'
+      local v = harfbuzz.Variation.new(vs)
+      assert.are_equal(vs, tostring(v))
+    end)
+
+    it("has visible fields", function()
+      local v = harfbuzz.Variation.new('wght=400')
+      assert.are_equal(tostring(v.tag), 'wght')
+      assert.are_equal(v.value, 400)
+
+      v = harfbuzz.Variation.new('slnt=-7.5')
+      assert.are_equal(tostring(v.tag), 'slnt')
+      assert.are_equal(v.value, -7.5)
+    end)
+
+    it("has editable fields", function()
+      local f = harfbuzz.Variation.new('slnt=5')
+      f.tag, f.value = harfbuzz.Tag.new"wght", 7
+      assert.are_equal(tostring(f), "wght=7")
+
+      f.tag, f.value = harfbuzz.Tag.new"hght", 0
+      assert.are_equal(tostring(f), "hght=0")
+    end)
+  end)
+
   describe("harfbuzz.Tag", function()
     it("can be initialised with a valid tag string", function()
       harfbuzz.Tag.new('Zyyy')
diff --git a/source/texk/web2c/luatexdir/luaharfbuzz/src/luaharfbuzz/face.c b/source/texk/web2c/luatexdir/luaharfbuzz/src/luaharfbuzz/face.c
index 5538c7045..45296e045 100644
--- a/source/texk/web2c/luatexdir/luaharfbuzz/src/luaharfbuzz/face.c
+++ b/source/texk/web2c/luatexdir/luaharfbuzz/src/luaharfbuzz/face.c
@@ -1,5 +1,20 @@
 #include "luaharfbuzz.h"
 
+#ifdef LuajitTeX
+
+static int lua_absindex (lua_State *L, int i) {
+  if (i < 0 && i > LUA_REGISTRYINDEX)
+    i += lua_gettop(L) + 1;
+  return i;
+}
+static void lua_seti (lua_State *L, int index, lua_Integer i) {
+  index = lua_absindex(L, index);
+  lua_pushinteger(L, i);
+  lua_insert(L, -2);
+  lua_settable(L, index);
+}
+#endif
+
 /* Size of static arrays we use to avoid heap allocating memory when reading
  * data from HarfBuzz. */
 #define STATIC_ARRAY_SIZE 128
@@ -423,6 +438,179 @@ static int face_ot_color_glyph_get_svg(lua_State *L) {
   return 1;
 }
 
+static int face_var_has_data(lua_State *L) {
+  Face *f = (Face *)luaL_checkudata(L, 1, "harfbuzz.Face");
+
+  lua_pushboolean(L, hb_ot_var_has_data(*f));
+  return 1;
+}
+
+static int push_axis_info(lua_State *L, const hb_ot_var_axis_info_t *info) {
+  lua_createtable(L, 0, 7);
+
+  lua_pushinteger(L, info->axis_index + 1);
+  lua_setfield(L, -2, "axis_index");
+
+  Tag *tp = (Tag *)lua_newuserdata(L, sizeof(*tp));
+  luaL_getmetatable(L, "harfbuzz.Tag");
+  lua_setmetatable(L, -2);
+  *tp = info->tag;
+  lua_setfield(L, -2, "tag");
+
+  lua_pushinteger(L, info->name_id);
+  lua_setfield(L, -2, "name_id");
+
+  lua_pushinteger(L, info->flags);
+  lua_setfield(L, -2, "flags");
+
+  lua_pushnumber(L, info->min_value);
+  lua_setfield(L, -2, "min_value");
+
+  lua_pushnumber(L, info->default_value);
+  lua_setfield(L, -2, "default_value");
+
+  lua_pushnumber(L, info->max_value);
+  lua_setfield(L, -2, "max_value");
+
+  return 1;
+}
+
+static int face_var_find_axis_info(lua_State *L) {
+  Face *face = (Face *)luaL_checkudata(L, 1, "harfbuzz.Face");
+  Tag *tag = (Tag *)luaL_checkudata(L, 2, "harfbuzz.Tag");
+  hb_ot_var_axis_info_t axis_info;
+
+  if (hb_ot_var_find_axis_info(*face, *tag, &axis_info))
+    push_axis_info(L, &axis_info);
+  else
+    lua_pushnil(L);
+  return 1;
+}
+
+static int face_var_get_axis_infos(lua_State *L) {
+  Face *face = (Face *)luaL_checkudata(L, 1, "harfbuzz.Face");
+  lua_Integer start = luaL_optinteger(L, 2, 1) - 1;
+  lua_Integer stop = luaL_optinteger(L, 2, -1);
+  if (start < -1)
+    start += hb_ot_var_get_axis_count(*face) + 1;
+  if (stop < 0)
+    stop += hb_ot_var_get_axis_count(*face) + 1;
+
+  if (start < 0 || stop - start > STATIC_ARRAY_SIZE)
+    lua_pushnil(L);
+  else if (stop <= start)
+    lua_createtable(L, 0, 0);
+  else {
+    unsigned int count = stop - start;
+    hb_ot_var_axis_info_t axis_infos[STATIC_ARRAY_SIZE];
+
+    hb_ot_var_get_axis_infos(*face, start, &count, axis_infos);
+
+    lua_createtable(L, count, 0);
+    for (int i = 0; i != count; i++) {
+      push_axis_info(L, axis_infos + i);
+      lua_seti(L, -2, i + 1);
+    }
+  }
+  return 1;
+}
+
+static int face_var_named_instance_get_infos(lua_State *L) {
+  Face *face = (Face *)luaL_checkudata(L, 1, "harfbuzz.Face");
+  lua_Integer start = luaL_optinteger(L, 2, 1) - 1;
+  lua_Integer stop = luaL_optinteger(L, 2, -1);
+
+  unsigned int total = hb_ot_var_get_named_instance_count(*face);
+
+  if (start < -1)
+    start += total + 1;
+  if (stop < 0)
+    stop += total + 1;
+  if (stop > total)
+    stop = total;
+
+  if (start < 0)
+    lua_pushnil(L);
+  else if (stop <= start)
+    lua_createtable(L, 0, 0);
+  else {
+    lua_createtable(L, stop - start, 0);
+    for (int i = start; i != stop; i++) {
+      lua_createtable(L, 0, 3);
+
+      lua_pushinteger(L, i + 1);
+      lua_setfield(L, -2, "index");
+
+      lua_pushinteger(L, hb_ot_var_named_instance_get_subfamily_name_id(*face, i));
+      lua_setfield(L, -2, "subfamily_name_id");
+
+      lua_pushinteger(L, hb_ot_var_named_instance_get_subfamily_name_id(*face, i));
+      lua_setfield(L, -2, "subfamily_name_id");
+
+      lua_pushinteger(L, hb_ot_var_named_instance_get_postscript_name_id(*face, i));
+      lua_setfield(L, -2, "postscript_name_id");
+
+      lua_seti(L, -2, i - start + 1);
+    }
+  }
+  return 1;
+}
+
+static int face_var_named_instance_get_design_coords(lua_State *L) {
+  Face *face = (Face *)luaL_checkudata(L, 1, "harfbuzz.Face");
+  lua_Integer index = luaL_checkinteger(L, 2) - 1;
+
+  float coords[STATIC_ARRAY_SIZE];
+  unsigned int count = STATIC_ARRAY_SIZE;
+  count = hb_ot_var_named_instance_get_design_coords(*face, index, &count, coords);
+
+  for (int i = 0; i != count; i++) {
+    lua_pushnumber(L, coords[i]);
+  }
+  return count;
+}
+
+static int face_var_normalize_variations(lua_State *L) {
+  Face *face = (Face *)luaL_checkudata(L, 1, "harfbuzz.Face");
+  unsigned int count = lua_gettop(L)-1;
+  if (count > STATIC_ARRAY_SIZE) {
+    return 0;
+  }
+
+  Variation variations[STATIC_ARRAY_SIZE];
+  for (unsigned int i = 0; i != count; i++)
+    variations[i] = *(Variation *)luaL_checkudata(L, i+2, "harfbuzz.Variation");
+
+  unsigned int coord_count = hb_ot_var_get_axis_count(*face);
+  int normalized[STATIC_ARRAY_SIZE];
+  hb_ot_var_normalize_variations(*face, variations, count, normalized, coord_count);
+
+  for (int i = 0; i != coord_count; i++) {
+    lua_pushinteger(L, normalized[i]);
+  }
+  return coord_count;
+}
+
+static int face_var_normalize_coords(lua_State *L) {
+  Face *face = (Face *)luaL_checkudata(L, 1, "harfbuzz.Face");
+  unsigned int count = lua_gettop(L)-1;
+  if (count > STATIC_ARRAY_SIZE) {
+    return 0;
+  }
+
+  float coords[STATIC_ARRAY_SIZE];
+  for (unsigned int i = 0; i != count; i++)
+    coords[i] = luaL_checknumber(L, i+2);
+
+  int normalized[STATIC_ARRAY_SIZE];
+  hb_ot_var_normalize_coords(*face, count, coords, normalized);
+
+  for (int i = 0; i != count; i++) {
+    lua_pushinteger(L, normalized[i]);
+  }
+  return count;
+}
+
 static int face_destroy(lua_State *L) {
   Face *f = (Face *)luaL_checkudata(L, 1, "harfbuzz.Face");
 
@@ -452,6 +640,13 @@ static const struct luaL_Reg face_methods[] = {
   { "ot_layout_find_script", face_ot_layout_find_script },
   { "ot_layout_find_language", face_ot_layout_find_language },
   { "ot_layout_find_feature", face_ot_layout_find_feature },
+  { "ot_var_has_data", face_var_has_data },
+  { "ot_var_find_axis_info", face_var_find_axis_info },
+  { "ot_var_get_axis_infos", face_var_get_axis_infos },
+  { "ot_var_named_instance_get_infos", face_var_named_instance_get_infos },
+  { "ot_var_named_instance_get_design_coords", face_var_named_instance_get_design_coords },
+  { "ot_var_normalize_variations", face_var_normalize_variations },
+  { "ot_var_normalize_coords", face_var_normalize_coords },
   { NULL, NULL }
 };
 
diff --git a/source/texk/web2c/luatexdir/luaharfbuzz/src/luaharfbuzz/font.c b/source/texk/web2c/luatexdir/luaharfbuzz/src/luaharfbuzz/font.c
index c60167364..2734534a2 100644
--- a/source/texk/web2c/luatexdir/luaharfbuzz/src/luaharfbuzz/font.c
+++ b/source/texk/web2c/luatexdir/luaharfbuzz/src/luaharfbuzz/font.c
@@ -192,6 +192,62 @@ static int font_ot_color_glyph_get_png(lua_State *L) {
   return 1;
 }
 
+static int font_set_variations(lua_State *L) {
+  Font *f = (Font *)luaL_checkudata(L, 1, "harfbuzz.Font");
+  unsigned int count = lua_gettop(L) - 1;
+  if (count > 128)
+    count = 128;
+  Variation variations[128];
+  for (int i = 0; i != count; i++)
+    variations[i] = *(Variation *)luaL_checkudata(L, i + 2, "harfbuzz.Variation");
+
+  hb_font_set_variations(*f, variations, count);
+  return 0;
+}
+
+static int font_set_var_coords_design(lua_State *L) {
+  Font *f = (Font *)luaL_checkudata(L, 1, "harfbuzz.Font");
+  unsigned int count = lua_gettop(L) - 1;
+  if (count > 128)
+    count = 128;
+  float coords[128];
+  for (int i = 0; i != count; i++)
+    coords[i] = luaL_checknumber(L, i + 2);
+
+  hb_font_set_var_coords_design(*f, coords, count);
+  return 0;
+}
+
+static int font_set_var_coords_normalized(lua_State *L) {
+  Font *f = (Font *)luaL_checkudata(L, 1, "harfbuzz.Font");
+  unsigned int count = lua_gettop(L) - 1;
+  if (count > 128)
+    count = 128;
+  int coords[128];
+  for (int i = 0; i != count; i++)
+    coords[i] = luaL_checkinteger(L, i + 2);
+
+  hb_font_set_var_coords_normalized(*f, coords, count);
+  return 0;
+}
+
+static int font_set_var_named_instance(lua_State *L) {
+  Font *f = (Font *)luaL_checkudata(L, 1, "harfbuzz.Font");
+  unsigned int instance = luaL_checkinteger(L, 2);
+
+  hb_font_set_var_named_instance(*f, instance);
+  return 0;
+}
+
+static int font_get_var_coords_normalized(lua_State *L) {
+  Font *f = (Font *)luaL_checkudata(L, 1, "harfbuzz.Font");
+  unsigned int count;
+  const int *coords = hb_font_get_var_coords_normalized(*f, &count);
+  for (int i = 0; i != count; i++)
+    lua_pushinteger(L, coords[i]);
+  return count;
+}
+
 static const struct luaL_Reg font_methods[] = {
   { "__gc", font_destroy },
   { "set_scale", font_set_scale },
@@ -205,6 +261,11 @@ static const struct luaL_Reg font_methods[] = {
   { "get_glyph_v_advance", font_get_glyph_v_advance },
   { "get_nominal_glyph", font_get_nominal_glyph },
   { "ot_color_glyph_get_png", font_ot_color_glyph_get_png },
+  { "set_variations", font_set_variations },
+  { "set_var_coords_design", font_set_var_coords_design },
+  { "set_var_coords_normalized", font_set_var_coords_normalized },
+  { "set_var_named_instance", font_set_var_named_instance },
+  { "get_var_coords_normalized", font_get_var_coords_normalized },
   { NULL, NULL }
 };
 
diff --git a/source/texk/web2c/luatexdir/luaharfbuzz/src/luaharfbuzz/luaharfbuzz.c b/source/texk/web2c/luatexdir/luaharfbuzz/src/luaharfbuzz/luaharfbuzz.c
index 176c552aa..8c841e563 100644
--- a/source/texk/web2c/luatexdir/luaharfbuzz/src/luaharfbuzz/luaharfbuzz.c
+++ b/source/texk/web2c/luatexdir/luaharfbuzz/src/luaharfbuzz/luaharfbuzz.c
@@ -103,6 +103,9 @@ int luaopen_luaharfbuzz (lua_State *L) {
   register_language(L);
   lua_setfield(L, -2, "Language");
 
+  register_variation(L);
+  lua_setfield(L, -2, "Variation");
+
   register_ot(L);
   lua_setfield(L, -2, "ot");
 
diff --git a/source/texk/web2c/luatexdir/luaharfbuzz/src/luaharfbuzz/luaharfbuzz.h b/source/texk/web2c/luatexdir/luaharfbuzz/src/luaharfbuzz/luaharfbuzz.h
index 60f5db9c2..4b3aea6f5 100644
--- a/source/texk/web2c/luatexdir/luaharfbuzz/src/luaharfbuzz/luaharfbuzz.h
+++ b/source/texk/web2c/luatexdir/luaharfbuzz/src/luaharfbuzz/luaharfbuzz.h
@@ -18,6 +18,7 @@ typedef hb_tag_t Tag;
 typedef hb_script_t Script;
 typedef hb_direction_t Direction;
 typedef hb_language_t Language;
+typedef hb_variation_t Variation;
 
 typedef struct luahb_constant_t {
   const char *name;
@@ -35,6 +36,7 @@ int register_tag(lua_State *L);
 int register_script(lua_State *L);
 int register_direction(lua_State *L);
 int register_language(lua_State *L);
+int register_variation(lua_State *L);
 int register_ot(lua_State *L);
 int register_unicode(lua_State *L);
 
diff --git a/source/texk/web2c/luatexdir/luaharfbuzz/src/luaharfbuzz/variation.c b/source/texk/web2c/luatexdir/luaharfbuzz/src/luaharfbuzz/variation.c
new file mode 100644
index 000000000..5683aa607
--- /dev/null
+++ b/source/texk/web2c/luatexdir/luaharfbuzz/src/luaharfbuzz/variation.c
@@ -0,0 +1,82 @@
+// harfbuzz.Variation
+#include "luaharfbuzz.h"
+
+static int variation_new(lua_State *L) {
+  Variation v;
+  const char *variation = luaL_checkstring(L, 1);
+
+  if (hb_variation_from_string(variation, -1, &v)) {
+    Variation *vp = (Variation *)lua_newuserdata(L, sizeof(*vp));
+    luaL_getmetatable(L, "harfbuzz.Variation");
+    lua_setmetatable(L, -2);
+    *vp = v;
+  } else {
+    lua_pushnil(L);
+  }
+
+  return 1;
+}
+
+static int variation_to_string(lua_State *L) {
+  Variation* v = (Variation *)luaL_checkudata(L, 1, "harfbuzz.Variation");
+  char variation[128];
+
+  hb_variation_to_string(v, variation, 128);
+  lua_pushstring(L, variation);
+  return 1;
+}
+
+static const char *variation_tag_ptr;
+static const char *variation_value_ptr;
+
+static int variation_index(lua_State *L) {
+  Variation* v = (Variation *)luaL_checkudata(L, 1, "harfbuzz.Variation");
+  const char *key = lua_tostring(L, 2);
+
+  if (key == variation_tag_ptr) {
+    Tag *tag = (Tag *)lua_newuserdata(L, sizeof(*tag));
+    luaL_getmetatable(L, "harfbuzz.Tag");
+    lua_setmetatable(L, -2);
+    *tag = v->tag;
+  } else if (key == variation_value_ptr) {
+    lua_pushnumber(L, v->value);
+  } else {
+    lua_pushnil(L);
+  }
+  return 1;
+}
+
+static int variation_newindex(lua_State *L) {
+  Variation* v = (Variation *)luaL_checkudata(L, 1, "harfbuzz.Variation");
+  const char *key = lua_tostring(L, 2);
+
+  if (key == variation_tag_ptr) {
+    v->tag = *(Tag *)luaL_checkudata(L, 3, "harfbuzz.Tag");
+  } else if (key == variation_value_ptr) {
+    v->value = luaL_checknumber(L, 3);
+  }
+  return 0;
+}
+
+static const struct luaL_Reg variation_methods[] = {
+  { "__index", variation_index },
+  { "__newindex", variation_newindex },
+  { "__tostring", variation_to_string },
+  { NULL, NULL },
+};
+
+static const struct luaL_Reg variation_functions[] = {
+  { "new", variation_new },
+  { NULL,  NULL }
+};
+
+int register_variation(lua_State *L) {
+  lua_pushliteral(L, "tag");
+  variation_tag_ptr = lua_tostring(L, -1);
+  (void) luaL_ref (L, LUA_REGISTRYINDEX);
+  lua_pushliteral(L, "value");
+  variation_value_ptr = lua_tostring(L, -1);
+  (void) luaL_ref (L, LUA_REGISTRYINDEX);
+
+  return register_class(L, "harfbuzz.Variation", variation_methods, variation_functions, NULL);
+}
-- 
2.32.0

-------------- next part --------------
>From d43d2306d14414810240c4acc6f5980400ad1c19 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Marcel=20Fabian=20Kr=C3=BCger?= <tex at 2krueger.de>
Date: Mon, 2 Aug 2021 03:01:24 +0200
Subject: [PATCH 1/2] Add interface for font variations in luaharfbuzz

---
 source/texk/web2c/Makefile.in                 |  39 +++-
 source/texk/web2c/luatexdir/am/luaharfbuzz.am |   3 +-
 .../luaharfbuzz/luaharfbuzz-1.1.0-1.rockspec  |   1 +
 .../luaharfbuzz/luaharfbuzz-scm-1.rockspec    |   1 +
 .../luaharfbuzz/spec/harfbuzz_spec.lua        | 116 ++++++++++-
 .../luaharfbuzz/src/luaharfbuzz/face.c        | 195 ++++++++++++++++++
 .../luaharfbuzz/src/luaharfbuzz/font.c        |  61 ++++++
 .../luaharfbuzz/src/luaharfbuzz/luaharfbuzz.c |   3 +
 .../luaharfbuzz/src/luaharfbuzz/luaharfbuzz.h |   2 +
 .../luaharfbuzz/src/luaharfbuzz/variation.c   |  82 ++++++++
 10 files changed, 498 insertions(+), 5 deletions(-)
 create mode 100644 source/texk/web2c/luatexdir/luaharfbuzz/src/luaharfbuzz/variation.c

diff --git a/source/texk/web2c/Makefile.in b/source/texk/web2c/Makefile.in
index 0542d8baf..b3c0de885 100644
--- a/source/texk/web2c/Makefile.in
+++ b/source/texk/web2c/Makefile.in
@@ -595,7 +595,8 @@ am_libluaharfbuzz_a_OBJECTS = luatexdir/luaharfbuzz/src/luaharfbuzz/libluaharfbu
 	luatexdir/luaharfbuzz/src/luaharfbuzz/libluaharfbuzz_a-ot.$(OBJEXT) \
 	luatexdir/luaharfbuzz/src/luaharfbuzz/libluaharfbuzz_a-script.$(OBJEXT) \
 	luatexdir/luaharfbuzz/src/luaharfbuzz/libluaharfbuzz_a-tag.$(OBJEXT) \
-	luatexdir/luaharfbuzz/src/luaharfbuzz/libluaharfbuzz_a-unicode.$(OBJEXT)
+	luatexdir/luaharfbuzz/src/luaharfbuzz/libluaharfbuzz_a-unicode.$(OBJEXT) \
+	luatexdir/luaharfbuzz/src/luaharfbuzz/libluaharfbuzz_a-variation.$(OBJEXT)
 libluaharfbuzz_a_OBJECTS = $(am_libluaharfbuzz_a_OBJECTS)
 libluahbtexspecific_a_AR = $(AR) $(ARFLAGS)
 libluahbtexspecific_a_LIBADD =
@@ -620,7 +621,8 @@ am__objects_3 = luatexdir/luaharfbuzz/src/luaharfbuzz/libluajitharfbuzz_a-blob.$
 	luatexdir/luaharfbuzz/src/luaharfbuzz/libluajitharfbuzz_a-ot.$(OBJEXT) \
 	luatexdir/luaharfbuzz/src/luaharfbuzz/libluajitharfbuzz_a-script.$(OBJEXT) \
 	luatexdir/luaharfbuzz/src/luaharfbuzz/libluajitharfbuzz_a-tag.$(OBJEXT) \
-	luatexdir/luaharfbuzz/src/luaharfbuzz/libluajitharfbuzz_a-unicode.$(OBJEXT)
+	luatexdir/luaharfbuzz/src/luaharfbuzz/libluajitharfbuzz_a-unicode.$(OBJEXT) \
+	luatexdir/luaharfbuzz/src/luaharfbuzz/libluajitharfbuzz_a-variation.$(OBJEXT)
 am_libluajitharfbuzz_a_OBJECTS = $(am__objects_3)
 libluajitharfbuzz_a_OBJECTS = $(am_libluajitharfbuzz_a_OBJECTS)
 libluajithbtexspecific_a_AR = $(AR) $(ARFLAGS)
@@ -1891,6 +1893,7 @@ am__depfiles_remade = ./$(DEPDIR)/aleph-aleph-pool.Po \
 	luatexdir/luaharfbuzz/src/luaharfbuzz/$(DEPDIR)/libluaharfbuzz_a-script.Po \
 	luatexdir/luaharfbuzz/src/luaharfbuzz/$(DEPDIR)/libluaharfbuzz_a-tag.Po \
 	luatexdir/luaharfbuzz/src/luaharfbuzz/$(DEPDIR)/libluaharfbuzz_a-unicode.Po \
+	luatexdir/luaharfbuzz/src/luaharfbuzz/$(DEPDIR)/libluaharfbuzz_a-variation.Po \
 	luatexdir/luaharfbuzz/src/luaharfbuzz/$(DEPDIR)/libluajitharfbuzz_a-blob.Po \
 	luatexdir/luaharfbuzz/src/luaharfbuzz/$(DEPDIR)/libluajitharfbuzz_a-buffer.Po \
 	luatexdir/luaharfbuzz/src/luaharfbuzz/$(DEPDIR)/libluajitharfbuzz_a-class_utils.Po \
@@ -1904,6 +1907,7 @@ am__depfiles_remade = ./$(DEPDIR)/aleph-aleph-pool.Po \
 	luatexdir/luaharfbuzz/src/luaharfbuzz/$(DEPDIR)/libluajitharfbuzz_a-script.Po \
 	luatexdir/luaharfbuzz/src/luaharfbuzz/$(DEPDIR)/libluajitharfbuzz_a-tag.Po \
 	luatexdir/luaharfbuzz/src/luaharfbuzz/$(DEPDIR)/libluajitharfbuzz_a-unicode.Po \
+	luatexdir/luaharfbuzz/src/luaharfbuzz/$(DEPDIR)/libluajitharfbuzz_a-variation.Po \
 	luatexdir/luamd5/$(DEPDIR)/libluajitmisc_a-md5.Po \
 	luatexdir/luamd5/$(DEPDIR)/libluajitmisc_a-md5lib.Po \
 	luatexdir/luamd5/$(DEPDIR)/libluamisc_a-md5.Po \
@@ -4725,7 +4729,8 @@ libluaharfbuzz_a_SOURCES = \
 	luatexdir/luaharfbuzz/src/luaharfbuzz/ot.c \
 	luatexdir/luaharfbuzz/src/luaharfbuzz/script.c \
 	luatexdir/luaharfbuzz/src/luaharfbuzz/tag.c \
-	luatexdir/luaharfbuzz/src/luaharfbuzz/unicode.c
+	luatexdir/luaharfbuzz/src/luaharfbuzz/unicode.c \
+	luatexdir/luaharfbuzz/src/luaharfbuzz/variation.c
 
 libluajitharfbuzz_a_SOURCES = $(libluaharfbuzz_a_SOURCES)
 
@@ -8728,6 +8733,20 @@ luatexdir/luaharfbuzz/src/luaharfbuzz/libluaharfbuzz_a-unicode.obj: luatexdir/lu
 @AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
 @am__fastdepCC_FALSE@	$(AM_V_CC at am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libluaharfbuzz_a_CPPFLAGS) $(CPPFLAGS) $(libluaharfbuzz_a_CFLAGS) $(CFLAGS) -c -o luatexdir/luaharfbuzz/src/luaharfbuzz/libluaharfbuzz_a-unicode.obj `if test -f 'luatexdir/luaharfbuzz/src/luaharfbuzz/unicode.c'; then $(CYGPATH_W) 'luatexdir/luaharfbuzz/src/luaharfbuzz/unicode.c'; else $(CYGPATH_W) '$(srcdir)/luatexdir/luaharfbuzz/src/luaharfbuzz/unicode.c'; fi`
 
+luatexdir/luaharfbuzz/src/luaharfbuzz/libluaharfbuzz_a-variation.o: luatexdir/luaharfbuzz/src/luaharfbuzz/variation.c
+ at am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libluaharfbuzz_a_CPPFLAGS) $(CPPFLAGS) $(libluaharfbuzz_a_CFLAGS) $(CFLAGS) -MT luatexdir/luaharfbuzz/src/luaharfbuzz/libluaharfbuzz_a-variation.o -MD -MP -MF luatexdir/luaharfbuzz/src/luaharfbuzz/$(DEPDIR)/libluaharfbuzz_a-variation.Tpo -c -o luatexdir/luaharfbuzz/src/luaharfbuzz/libluaharfbuzz_a-variation.o `test -f 'luatexdir/luaharfbuzz/src/luaharfbuzz/variation.c' || echo '$(srcdir)/'`luatexdir/luaharfbuzz/src/luaharfbuzz/variation.c
+ at am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) luatexdir/luaharfbuzz/src/luaharfbuzz/$(DEPDIR)/libluaharfbuzz_a-variation.Tpo luatexdir/luaharfbuzz/src/luaharfbuzz/$(DEPDIR)/libluaharfbuzz_a-variation.Po
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='luatexdir/luaharfbuzz/src/luaharfbuzz/variation.c' object='luatexdir/luaharfbuzz/src/luaharfbuzz/libluaharfbuzz_a-variation.o' libtool=no @AMDEPBACKSLASH@
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+ at am__fastdepCC_FALSE@	$(AM_V_CC at am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libluaharfbuzz_a_CPPFLAGS) $(CPPFLAGS) $(libluaharfbuzz_a_CFLAGS) $(CFLAGS) -c -o luatexdir/luaharfbuzz/src/luaharfbuzz/libluaharfbuzz_a-variation.o `test -f 'luatexdir/luaharfbuzz/src/luaharfbuzz/variation.c' || echo '$(srcdir)/'`luatexdir/luaharfbuzz/src/luaharfbuzz/variation.c
+
+luatexdir/luaharfbuzz/src/luaharfbuzz/libluaharfbuzz_a-variation.obj: luatexdir/luaharfbuzz/src/luaharfbuzz/variation.c
+ at am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libluaharfbuzz_a_CPPFLAGS) $(CPPFLAGS) $(libluaharfbuzz_a_CFLAGS) $(CFLAGS) -MT luatexdir/luaharfbuzz/src/luaharfbuzz/libluaharfbuzz_a-variation.obj -MD -MP -MF luatexdir/luaharfbuzz/src/luaharfbuzz/$(DEPDIR)/libluaharfbuzz_a-variation.Tpo -c -o luatexdir/luaharfbuzz/src/luaharfbuzz/libluaharfbuzz_a-variation.obj `if test -f 'luatexdir/luaharfbuzz/src/luaharfbuzz/variation.c'; then $(CYGPATH_W) 'luatexdir/luaharfbuzz/src/luaharfbuzz/variation.c'; else $(CYGPATH_W) '$(srcdir)/luatexdir/luaharfbuzz/src/luaharfbuzz/variation.c'; fi`
+ at am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) luatexdir/luaharfbuzz/src/luaharfbuzz/$(DEPDIR)/libluaharfbuzz_a-variation.Tpo luatexdir/luaharfbuzz/src/luaharfbuzz/$(DEPDIR)/libluaharfbuzz_a-variation.Po
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='luatexdir/luaharfbuzz/src/luaharfbuzz/variation.c' object='luatexdir/luaharfbuzz/src/luaharfbuzz/libluaharfbuzz_a-variation.obj' libtool=no @AMDEPBACKSLASH@
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+ at am__fastdepCC_FALSE@	$(AM_V_CC at am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libluaharfbuzz_a_CPPFLAGS) $(CPPFLAGS) $(libluaharfbuzz_a_CFLAGS) $(CFLAGS) -c -o luatexdir/luaharfbuzz/src/luaharfbuzz/libluaharfbuzz_a-variation.obj `if test -f 'luatexdir/luaharfbuzz/src/luaharfbuzz/variation.c'; then $(CYGPATH_W) 'luatexdir/luaharfbuzz/src/luaharfbuzz/variation.c'; else $(CYGPATH_W) '$(srcdir)/luatexdir/luaharfbuzz/src/luaharfbuzz/variation.c'; fi`
+
 libluahbtexspecific_a-utils-hb.o: utils-hb.c
 @am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libluahbtexspecific_a_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libluahbtexspecific_a-utils-hb.o -MD -MP -MF $(DEPDIR)/libluahbtexspecific_a-utils-hb.Tpo -c -o libluahbtexspecific_a-utils-hb.o `test -f 'utils-hb.c' || echo '$(srcdir)/'`utils-hb.c
 @am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/libluahbtexspecific_a-utils-hb.Tpo $(DEPDIR)/libluahbtexspecific_a-utils-hb.Po
@@ -8966,6 +8985,20 @@ luatexdir/luaharfbuzz/src/luaharfbuzz/libluajitharfbuzz_a-unicode.obj: luatexdir
 @AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
 @am__fastdepCC_FALSE@	$(AM_V_CC at am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libluajitharfbuzz_a_CPPFLAGS) $(CPPFLAGS) $(libluajitharfbuzz_a_CFLAGS) $(CFLAGS) -c -o luatexdir/luaharfbuzz/src/luaharfbuzz/libluajitharfbuzz_a-unicode.obj `if test -f 'luatexdir/luaharfbuzz/src/luaharfbuzz/unicode.c'; then $(CYGPATH_W) 'luatexdir/luaharfbuzz/src/luaharfbuzz/unicode.c'; else $(CYGPATH_W) '$(srcdir)/luatexdir/luaharfbuzz/src/luaharfbuzz/unicode.c'; fi`
 
+luatexdir/luaharfbuzz/src/luaharfbuzz/libluajitharfbuzz_a-variation.o: luatexdir/luaharfbuzz/src/luaharfbuzz/variation.c
+ at am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libluajitharfbuzz_a_CPPFLAGS) $(CPPFLAGS) $(libluajitharfbuzz_a_CFLAGS) $(CFLAGS) -MT luatexdir/luaharfbuzz/src/luaharfbuzz/libluajitharfbuzz_a-variation.o -MD -MP -MF luatexdir/luaharfbuzz/src/luaharfbuzz/$(DEPDIR)/libluajitharfbuzz_a-variation.Tpo -c -o luatexdir/luaharfbuzz/src/luaharfbuzz/libluajitharfbuzz_a-variation.o `test -f 'luatexdir/luaharfbuzz/src/luaharfbuzz/variation.c' || echo '$(srcdir)/'`luatexdir/luaharfbuzz/src/luaharfbuzz/variation.c
+ at am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) luatexdir/luaharfbuzz/src/luaharfbuzz/$(DEPDIR)/libluajitharfbuzz_a-variation.Tpo luatexdir/luaharfbuzz/src/luaharfbuzz/$(DEPDIR)/libluajitharfbuzz_a-variation.Po
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='luatexdir/luaharfbuzz/src/luaharfbuzz/variation.c' object='luatexdir/luaharfbuzz/src/luaharfbuzz/libluajitharfbuzz_a-variation.o' libtool=no @AMDEPBACKSLASH@
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+ at am__fastdepCC_FALSE@	$(AM_V_CC at am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libluajitharfbuzz_a_CPPFLAGS) $(CPPFLAGS) $(libluajitharfbuzz_a_CFLAGS) $(CFLAGS) -c -o luatexdir/luaharfbuzz/src/luaharfbuzz/libluajitharfbuzz_a-variation.o `test -f 'luatexdir/luaharfbuzz/src/luaharfbuzz/variation.c' || echo '$(srcdir)/'`luatexdir/luaharfbuzz/src/luaharfbuzz/variation.c
+
+luatexdir/luaharfbuzz/src/luaharfbuzz/libluajitharfbuzz_a-variation.obj: luatexdir/luaharfbuzz/src/luaharfbuzz/variation.c
+ at am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libluajitharfbuzz_a_CPPFLAGS) $(CPPFLAGS) $(libluajitharfbuzz_a_CFLAGS) $(CFLAGS) -MT luatexdir/luaharfbuzz/src/luaharfbuzz/libluajitharfbuzz_a-variation.obj -MD -MP -MF luatexdir/luaharfbuzz/src/luaharfbuzz/$(DEPDIR)/libluajitharfbuzz_a-variation.Tpo -c -o luatexdir/luaharfbuzz/src/luaharfbuzz/libluajitharfbuzz_a-variation.obj `if test -f 'luatexdir/luaharfbuzz/src/luaharfbuzz/variation.c'; then $(CYGPATH_W) 'luatexdir/luaharfbuzz/src/luaharfbuzz/variation.c'; else $(CYGPATH_W) '$(srcdir)/luatexdir/luaharfbuzz/src/luaharfbuzz/variation.c'; fi`
+ at am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) luatexdir/luaharfbuzz/src/luaharfbuzz/$(DEPDIR)/libluajitharfbuzz_a-variation.Tpo luatexdir/luaharfbuzz/src/luaharfbuzz/$(DEPDIR)/libluajitharfbuzz_a-variation.Po
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='luatexdir/luaharfbuzz/src/luaharfbuzz/variation.c' object='luatexdir/luaharfbuzz/src/luaharfbuzz/libluajitharfbuzz_a-variation.obj' libtool=no @AMDEPBACKSLASH@
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+ at am__fastdepCC_FALSE@	$(AM_V_CC at am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libluajitharfbuzz_a_CPPFLAGS) $(CPPFLAGS) $(libluajitharfbuzz_a_CFLAGS) $(CFLAGS) -c -o luatexdir/luaharfbuzz/src/luaharfbuzz/libluajitharfbuzz_a-variation.obj `if test -f 'luatexdir/luaharfbuzz/src/luaharfbuzz/variation.c'; then $(CYGPATH_W) 'luatexdir/luaharfbuzz/src/luaharfbuzz/variation.c'; else $(CYGPATH_W) '$(srcdir)/luatexdir/luaharfbuzz/src/luaharfbuzz/variation.c'; fi`
+
 libluajithbtexspecific_a-utils-hb.o: utils-hb.c
 @am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libluajithbtexspecific_a_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libluajithbtexspecific_a-utils-hb.o -MD -MP -MF $(DEPDIR)/libluajithbtexspecific_a-utils-hb.Tpo -c -o libluajithbtexspecific_a-utils-hb.o `test -f 'utils-hb.c' || echo '$(srcdir)/'`utils-hb.c
 @am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/libluajithbtexspecific_a-utils-hb.Tpo $(DEPDIR)/libluajithbtexspecific_a-utils-hb.Po
diff --git a/source/texk/web2c/luatexdir/am/luaharfbuzz.am b/source/texk/web2c/luatexdir/am/luaharfbuzz.am
index 1b6187eaa..f98dc79a0 100644
--- a/source/texk/web2c/luatexdir/am/luaharfbuzz.am
+++ b/source/texk/web2c/luatexdir/am/luaharfbuzz.am
@@ -35,7 +35,8 @@ libluaharfbuzz_a_SOURCES = \
 	luatexdir/luaharfbuzz/src/luaharfbuzz/ot.c \
 	luatexdir/luaharfbuzz/src/luaharfbuzz/script.c \
 	luatexdir/luaharfbuzz/src/luaharfbuzz/tag.c \
-	luatexdir/luaharfbuzz/src/luaharfbuzz/unicode.c
+	luatexdir/luaharfbuzz/src/luaharfbuzz/unicode.c \
+	luatexdir/luaharfbuzz/src/luaharfbuzz/variation.c
 
 libluajitharfbuzz_a_SOURCES = $(libluaharfbuzz_a_SOURCES)
 
diff --git a/source/texk/web2c/luatexdir/luaharfbuzz/luaharfbuzz-1.1.0-1.rockspec b/source/texk/web2c/luatexdir/luaharfbuzz/luaharfbuzz-1.1.0-1.rockspec
index 17a84532b..987e9748f 100644
--- a/source/texk/web2c/luatexdir/luaharfbuzz/luaharfbuzz-1.1.0-1.rockspec
+++ b/source/texk/web2c/luatexdir/luaharfbuzz/luaharfbuzz-1.1.0-1.rockspec
@@ -31,6 +31,7 @@ build = {
       "src/luaharfbuzz/script.c",
       "src/luaharfbuzz/direction.c",
       "src/luaharfbuzz/language.c",
+      "src/luaharfbuzz/variation.c",
       "src/luaharfbuzz/class_utils.c"
       },
       libraries = {"harfbuzz"},
diff --git a/source/texk/web2c/luatexdir/luaharfbuzz/luaharfbuzz-scm-1.rockspec b/source/texk/web2c/luatexdir/luaharfbuzz/luaharfbuzz-scm-1.rockspec
index 31ae2ab4f..0f0dd8d33 100644
--- a/source/texk/web2c/luatexdir/luaharfbuzz/luaharfbuzz-scm-1.rockspec
+++ b/source/texk/web2c/luatexdir/luaharfbuzz/luaharfbuzz-scm-1.rockspec
@@ -33,6 +33,7 @@ build = {
       "src/luaharfbuzz/script.c",
       "src/luaharfbuzz/direction.c",
       "src/luaharfbuzz/language.c",
+      "src/luaharfbuzz/variation.c",
       "src/luaharfbuzz/class_utils.c"
       },
       libraries = {"harfbuzz"},
diff --git a/source/texk/web2c/luatexdir/luaharfbuzz/spec/harfbuzz_spec.lua b/source/texk/web2c/luatexdir/luaharfbuzz/spec/harfbuzz_spec.lua
index dfae07d8e..38794372f 100644
--- a/source/texk/web2c/luatexdir/luaharfbuzz/spec/harfbuzz_spec.lua
+++ b/source/texk/web2c/luatexdir/luaharfbuzz/spec/harfbuzz_spec.lua
@@ -230,6 +230,64 @@ describe("harfbuzz module", function()
       assert.True(r)
       assert.are_same(13, i)
     end)
+
+    it("can return variation axes", function()
+      local f = harfbuzz.Face.new('fonts/STIXTwoText[wght].ttf')
+
+      assert.is_same(true, f:ot_var_has_data())
+      local axes = f:ot_var_get_axis_infos()
+      assert.are_same(1, #axes)
+      assert.are_same(harfbuzz.Tag.new("wght"), axes[1].tag)
+      assert.are_same(1, axes[1].axis_index)
+      assert.are_same(400, axes[1].min_value)
+      assert.are_same(400, axes[1].default_value)
+      assert.are_same(700, axes[1].max_value)
+      assert.are_same(0, axes[1].flags)
+      assert.are_same("Weight", f:get_name(axes[1].name_id))
+    end)
+
+    it("can find variation axis", function()
+      local f = harfbuzz.Face.new('fonts/STIXTwoText[wght].ttf')
+
+      local axis = f:ot_var_find_axis_info(harfbuzz.Tag.new("wght"))
+      assert.is_not_nil(axis)
+      assert.are_same(harfbuzz.Tag.new("wght"), axis.tag)
+      assert.are_same(1, axis.axis_index)
+      assert.are_same(400, axis.min_value)
+      assert.are_same(400, axis.default_value)
+      assert.are_same(700, axis.max_value)
+      assert.are_same(0, axis.flags)
+      assert.are_same("Weight", f:get_name(axis.name_id))
+    end)
+
+    it("can return named instances", function()
+      local f = harfbuzz.Face.new('fonts/STIXTwoText[wght].ttf')
+
+      local instances = f:ot_var_named_instance_get_infos()
+      assert.are_same(4, #instances)
+      assert.are_same(3, instances[3].index)
+      assert.are_same("SemiBold", f:get_name(instances[3].subfamily_name_id))
+      assert.are_same(nil, f:get_name(instances[3].postscript_name_id))
+      assert.are_same(600, f:ot_var_named_instance_get_design_coords(3))
+    end)
+
+    it("can normalize variations", function()
+      local f = harfbuzz.Face.new('fonts/STIXTwoText[wght].ttf')
+
+      local normalized, after = f:ot_var_normalize_variations(harfbuzz.Variation.new("wght=400"))
+      assert.is_nil(after)
+      assert.are_same(0, normalized)
+
+      normalized = f:ot_var_normalize_variations(harfbuzz.Variation.new("wght=700"))
+      assert.are_same(1<<14, normalized)
+
+      normalized, after = f:ot_var_normalize_coords(700)
+      assert.is_nil(after)
+      assert.are_same(1<<14, normalized)
+
+      normalized = f:ot_var_normalize_coords(400)
+      assert.are_same(0, normalized)
+    end)
   end)
 
   describe("harfbuzz.Font", function()
@@ -318,6 +376,25 @@ describe("harfbuzz module", function()
       assert.are_same(2857,f:ot_color_glyph_get_png(2):get_length())
       assert.are_same("\137PNG",f:ot_color_glyph_get_png(2):get_data():sub(1, 4))
     end)
+
+    it("can set variations", function()
+      local f = harfbuzz.Font.new(harfbuzz.Face.new('fonts/STIXTwoText[wght].ttf'))
+
+      f:set_variations(harfbuzz.Variation.new("wght=500"))
+      local normalized, after = f:get_var_coords_normalized()
+      assert.is_nil(after)
+      assert.are_same(5174, normalized)
+
+      f:set_var_coords_design(600)
+      local normalized, after = f:get_var_coords_normalized()
+      assert.is_nil(after)
+      assert.are_same(10348, normalized)
+
+      f:set_var_coords_normalized(1<<13)
+      local normalized, after = f:get_var_coords_normalized()
+      assert.is_nil(after)
+      assert.are_same(1<<13, normalized)
+    end)
   end)
 
   describe("harfbuzz.Feature", function()
@@ -339,7 +416,6 @@ describe("harfbuzz module", function()
 
     it("has visible fields", function()
       local f = harfbuzz.Feature.new('-kern')
-      print(getmetatable(f).__index)
       assert.are_equal(tostring(f.tag), 'kern')
       assert.are_equal(f.value, 0)
       assert.are_equal(f.start, nil)
@@ -362,6 +438,44 @@ describe("harfbuzz module", function()
     end)
   end)
 
+  describe("harfbuzz.Variation", function()
+    it("can be initialised with a valid variation string", function()
+      harfbuzz.Variation.new('wght=default')
+      harfbuzz.Variation.new('wght=400')
+      harfbuzz.Variation.new('wght=-20')
+    end)
+
+    it("throws an error when trying to initialise a new variation with an invalid string", function()
+       assert.are_equal(nil, harfbuzz.Variation.new(''))
+       assert.are_equal(nil, harfbuzz.Variation.new('wght'))
+    end)
+
+    it("has a valid tostring value", function()
+      local vs = 'wght=200'
+      local v = harfbuzz.Variation.new(vs)
+      assert.are_equal(vs, tostring(v))
+    end)
+
+    it("has visible fields", function()
+      local v = harfbuzz.Variation.new('wght=400')
+      assert.are_equal(tostring(v.tag), 'wght')
+      assert.are_equal(v.value, 400)
+
+      v = harfbuzz.Variation.new('slnt=-7.5')
+      assert.are_equal(tostring(v.tag), 'slnt')
+      assert.are_equal(v.value, -7.5)
+    end)
+
+    it("has editable fields", function()
+      local f = harfbuzz.Variation.new('slnt=5')
+      f.tag, f.value = harfbuzz.Tag.new"wght", 7
+      assert.are_equal(tostring(f), "wght=7")
+
+      f.tag, f.value = harfbuzz.Tag.new"hght", 0
+      assert.are_equal(tostring(f), "hght=0")
+    end)
+  end)
+
   describe("harfbuzz.Tag", function()
     it("can be initialised with a valid tag string", function()
       harfbuzz.Tag.new('Zyyy')
diff --git a/source/texk/web2c/luatexdir/luaharfbuzz/src/luaharfbuzz/face.c b/source/texk/web2c/luatexdir/luaharfbuzz/src/luaharfbuzz/face.c
index 5538c7045..45296e045 100644
--- a/source/texk/web2c/luatexdir/luaharfbuzz/src/luaharfbuzz/face.c
+++ b/source/texk/web2c/luatexdir/luaharfbuzz/src/luaharfbuzz/face.c
@@ -1,5 +1,20 @@
 #include "luaharfbuzz.h"
 
+#ifdef LuajitTeX
+
+static int lua_absindex (lua_State *L, int i) {
+  if (i < 0 && i > LUA_REGISTRYINDEX)
+    i += lua_gettop(L) + 1;
+  return i;
+}
+static void lua_seti (lua_State *L, int index, lua_Integer i) {
+  index = lua_absindex(L, index);
+  lua_pushinteger(L, i);
+  lua_insert(L, -2);
+  lua_settable(L, index);
+}
+#endif
+
 /* Size of static arrays we use to avoid heap allocating memory when reading
  * data from HarfBuzz. */
 #define STATIC_ARRAY_SIZE 128
@@ -423,6 +438,179 @@ static int face_ot_color_glyph_get_svg(lua_State *L) {
   return 1;
 }
 
+static int face_var_has_data(lua_State *L) {
+  Face *f = (Face *)luaL_checkudata(L, 1, "harfbuzz.Face");
+
+  lua_pushboolean(L, hb_ot_var_has_data(*f));
+  return 1;
+}
+
+static int push_axis_info(lua_State *L, const hb_ot_var_axis_info_t *info) {
+  lua_createtable(L, 0, 7);
+
+  lua_pushinteger(L, info->axis_index + 1);
+  lua_setfield(L, -2, "axis_index");
+
+  Tag *tp = (Tag *)lua_newuserdata(L, sizeof(*tp));
+  luaL_getmetatable(L, "harfbuzz.Tag");
+  lua_setmetatable(L, -2);
+  *tp = info->tag;
+  lua_setfield(L, -2, "tag");
+
+  lua_pushinteger(L, info->name_id);
+  lua_setfield(L, -2, "name_id");
+
+  lua_pushinteger(L, info->flags);
+  lua_setfield(L, -2, "flags");
+
+  lua_pushnumber(L, info->min_value);
+  lua_setfield(L, -2, "min_value");
+
+  lua_pushnumber(L, info->default_value);
+  lua_setfield(L, -2, "default_value");
+
+  lua_pushnumber(L, info->max_value);
+  lua_setfield(L, -2, "max_value");
+
+  return 1;
+}
+
+static int face_var_find_axis_info(lua_State *L) {
+  Face *face = (Face *)luaL_checkudata(L, 1, "harfbuzz.Face");
+  Tag *tag = (Tag *)luaL_checkudata(L, 2, "harfbuzz.Tag");
+  hb_ot_var_axis_info_t axis_info;
+
+  if (hb_ot_var_find_axis_info(*face, *tag, &axis_info))
+    push_axis_info(L, &axis_info);
+  else
+    lua_pushnil(L);
+  return 1;
+}
+
+static int face_var_get_axis_infos(lua_State *L) {
+  Face *face = (Face *)luaL_checkudata(L, 1, "harfbuzz.Face");
+  lua_Integer start = luaL_optinteger(L, 2, 1) - 1;
+  lua_Integer stop = luaL_optinteger(L, 2, -1);
+  if (start < -1)
+    start += hb_ot_var_get_axis_count(*face) + 1;
+  if (stop < 0)
+    stop += hb_ot_var_get_axis_count(*face) + 1;
+
+  if (start < 0 || stop - start > STATIC_ARRAY_SIZE)
+    lua_pushnil(L);
+  else if (stop <= start)
+    lua_createtable(L, 0, 0);
+  else {
+    unsigned int count = stop - start;
+    hb_ot_var_axis_info_t axis_infos[STATIC_ARRAY_SIZE];
+
+    hb_ot_var_get_axis_infos(*face, start, &count, axis_infos);
+
+    lua_createtable(L, count, 0);
+    for (int i = 0; i != count; i++) {
+      push_axis_info(L, axis_infos + i);
+      lua_seti(L, -2, i + 1);
+    }
+  }
+  return 1;
+}
+
+static int face_var_named_instance_get_infos(lua_State *L) {
+  Face *face = (Face *)luaL_checkudata(L, 1, "harfbuzz.Face");
+  lua_Integer start = luaL_optinteger(L, 2, 1) - 1;
+  lua_Integer stop = luaL_optinteger(L, 2, -1);
+
+  unsigned int total = hb_ot_var_get_named_instance_count(*face);
+
+  if (start < -1)
+    start += total + 1;
+  if (stop < 0)
+    stop += total + 1;
+  if (stop > total)
+    stop = total;
+
+  if (start < 0)
+    lua_pushnil(L);
+  else if (stop <= start)
+    lua_createtable(L, 0, 0);
+  else {
+    lua_createtable(L, stop - start, 0);
+    for (int i = start; i != stop; i++) {
+      lua_createtable(L, 0, 3);
+
+      lua_pushinteger(L, i + 1);
+      lua_setfield(L, -2, "index");
+
+      lua_pushinteger(L, hb_ot_var_named_instance_get_subfamily_name_id(*face, i));
+      lua_setfield(L, -2, "subfamily_name_id");
+
+      lua_pushinteger(L, hb_ot_var_named_instance_get_subfamily_name_id(*face, i));
+      lua_setfield(L, -2, "subfamily_name_id");
+
+      lua_pushinteger(L, hb_ot_var_named_instance_get_postscript_name_id(*face, i));
+      lua_setfield(L, -2, "postscript_name_id");
+
+      lua_seti(L, -2, i - start + 1);
+    }
+  }
+  return 1;
+}
+
+static int face_var_named_instance_get_design_coords(lua_State *L) {
+  Face *face = (Face *)luaL_checkudata(L, 1, "harfbuzz.Face");
+  lua_Integer index = luaL_checkinteger(L, 2) - 1;
+
+  float coords[STATIC_ARRAY_SIZE];
+  unsigned int count = STATIC_ARRAY_SIZE;
+  count = hb_ot_var_named_instance_get_design_coords(*face, index, &count, coords);
+
+  for (int i = 0; i != count; i++) {
+    lua_pushnumber(L, coords[i]);
+  }
+  return count;
+}
+
+static int face_var_normalize_variations(lua_State *L) {
+  Face *face = (Face *)luaL_checkudata(L, 1, "harfbuzz.Face");
+  unsigned int count = lua_gettop(L)-1;
+  if (count > STATIC_ARRAY_SIZE) {
+    return 0;
+  }
+
+  Variation variations[STATIC_ARRAY_SIZE];
+  for (unsigned int i = 0; i != count; i++)
+    variations[i] = *(Variation *)luaL_checkudata(L, i+2, "harfbuzz.Variation");
+
+  unsigned int coord_count = hb_ot_var_get_axis_count(*face);
+  int normalized[STATIC_ARRAY_SIZE];
+  hb_ot_var_normalize_variations(*face, variations, count, normalized, coord_count);
+
+  for (int i = 0; i != coord_count; i++) {
+    lua_pushinteger(L, normalized[i]);
+  }
+  return coord_count;
+}
+
+static int face_var_normalize_coords(lua_State *L) {
+  Face *face = (Face *)luaL_checkudata(L, 1, "harfbuzz.Face");
+  unsigned int count = lua_gettop(L)-1;
+  if (count > STATIC_ARRAY_SIZE) {
+    return 0;
+  }
+
+  float coords[STATIC_ARRAY_SIZE];
+  for (unsigned int i = 0; i != count; i++)
+    coords[i] = luaL_checknumber(L, i+2);
+
+  int normalized[STATIC_ARRAY_SIZE];
+  hb_ot_var_normalize_coords(*face, count, coords, normalized);
+
+  for (int i = 0; i != count; i++) {
+    lua_pushinteger(L, normalized[i]);
+  }
+  return count;
+}
+
 static int face_destroy(lua_State *L) {
   Face *f = (Face *)luaL_checkudata(L, 1, "harfbuzz.Face");
 
@@ -452,6 +640,13 @@ static const struct luaL_Reg face_methods[] = {
   { "ot_layout_find_script", face_ot_layout_find_script },
   { "ot_layout_find_language", face_ot_layout_find_language },
   { "ot_layout_find_feature", face_ot_layout_find_feature },
+  { "ot_var_has_data", face_var_has_data },
+  { "ot_var_find_axis_info", face_var_find_axis_info },
+  { "ot_var_get_axis_infos", face_var_get_axis_infos },
+  { "ot_var_named_instance_get_infos", face_var_named_instance_get_infos },
+  { "ot_var_named_instance_get_design_coords", face_var_named_instance_get_design_coords },
+  { "ot_var_normalize_variations", face_var_normalize_variations },
+  { "ot_var_normalize_coords", face_var_normalize_coords },
   { NULL, NULL }
 };
 
diff --git a/source/texk/web2c/luatexdir/luaharfbuzz/src/luaharfbuzz/font.c b/source/texk/web2c/luatexdir/luaharfbuzz/src/luaharfbuzz/font.c
index c60167364..2734534a2 100644
--- a/source/texk/web2c/luatexdir/luaharfbuzz/src/luaharfbuzz/font.c
+++ b/source/texk/web2c/luatexdir/luaharfbuzz/src/luaharfbuzz/font.c
@@ -192,6 +192,62 @@ static int font_ot_color_glyph_get_png(lua_State *L) {
   return 1;
 }
 
+static int font_set_variations(lua_State *L) {
+  Font *f = (Font *)luaL_checkudata(L, 1, "harfbuzz.Font");
+  unsigned int count = lua_gettop(L) - 1;
+  if (count > 128)
+    count = 128;
+  Variation variations[128];
+  for (int i = 0; i != count; i++)
+    variations[i] = *(Variation *)luaL_checkudata(L, i + 2, "harfbuzz.Variation");
+
+  hb_font_set_variations(*f, variations, count);
+  return 0;
+}
+
+static int font_set_var_coords_design(lua_State *L) {
+  Font *f = (Font *)luaL_checkudata(L, 1, "harfbuzz.Font");
+  unsigned int count = lua_gettop(L) - 1;
+  if (count > 128)
+    count = 128;
+  float coords[128];
+  for (int i = 0; i != count; i++)
+    coords[i] = luaL_checknumber(L, i + 2);
+
+  hb_font_set_var_coords_design(*f, coords, count);
+  return 0;
+}
+
+static int font_set_var_coords_normalized(lua_State *L) {
+  Font *f = (Font *)luaL_checkudata(L, 1, "harfbuzz.Font");
+  unsigned int count = lua_gettop(L) - 1;
+  if (count > 128)
+    count = 128;
+  int coords[128];
+  for (int i = 0; i != count; i++)
+    coords[i] = luaL_checkinteger(L, i + 2);
+
+  hb_font_set_var_coords_normalized(*f, coords, count);
+  return 0;
+}
+
+static int font_set_var_named_instance(lua_State *L) {
+  Font *f = (Font *)luaL_checkudata(L, 1, "harfbuzz.Font");
+  unsigned int instance = luaL_checkinteger(L, 2);
+
+  hb_font_set_var_named_instance(*f, instance);
+  return 0;
+}
+
+static int font_get_var_coords_normalized(lua_State *L) {
+  Font *f = (Font *)luaL_checkudata(L, 1, "harfbuzz.Font");
+  unsigned int count;
+  const int *coords = hb_font_get_var_coords_normalized(*f, &count);
+  for (int i = 0; i != count; i++)
+    lua_pushinteger(L, coords[i]);
+  return count;
+}
+
 static const struct luaL_Reg font_methods[] = {
   { "__gc", font_destroy },
   { "set_scale", font_set_scale },
@@ -205,6 +261,11 @@ static const struct luaL_Reg font_methods[] = {
   { "get_glyph_v_advance", font_get_glyph_v_advance },
   { "get_nominal_glyph", font_get_nominal_glyph },
   { "ot_color_glyph_get_png", font_ot_color_glyph_get_png },
+  { "set_variations", font_set_variations },
+  { "set_var_coords_design", font_set_var_coords_design },
+  { "set_var_coords_normalized", font_set_var_coords_normalized },
+  { "set_var_named_instance", font_set_var_named_instance },
+  { "get_var_coords_normalized", font_get_var_coords_normalized },
   { NULL, NULL }
 };
 
diff --git a/source/texk/web2c/luatexdir/luaharfbuzz/src/luaharfbuzz/luaharfbuzz.c b/source/texk/web2c/luatexdir/luaharfbuzz/src/luaharfbuzz/luaharfbuzz.c
index 176c552aa..8c841e563 100644
--- a/source/texk/web2c/luatexdir/luaharfbuzz/src/luaharfbuzz/luaharfbuzz.c
+++ b/source/texk/web2c/luatexdir/luaharfbuzz/src/luaharfbuzz/luaharfbuzz.c
@@ -103,6 +103,9 @@ int luaopen_luaharfbuzz (lua_State *L) {
   register_language(L);
   lua_setfield(L, -2, "Language");
 
+  register_variation(L);
+  lua_setfield(L, -2, "Variation");
+
   register_ot(L);
   lua_setfield(L, -2, "ot");
 
diff --git a/source/texk/web2c/luatexdir/luaharfbuzz/src/luaharfbuzz/luaharfbuzz.h b/source/texk/web2c/luatexdir/luaharfbuzz/src/luaharfbuzz/luaharfbuzz.h
index 60f5db9c2..4b3aea6f5 100644
--- a/source/texk/web2c/luatexdir/luaharfbuzz/src/luaharfbuzz/luaharfbuzz.h
+++ b/source/texk/web2c/luatexdir/luaharfbuzz/src/luaharfbuzz/luaharfbuzz.h
@@ -18,6 +18,7 @@ typedef hb_tag_t Tag;
 typedef hb_script_t Script;
 typedef hb_direction_t Direction;
 typedef hb_language_t Language;
+typedef hb_variation_t Variation;
 
 typedef struct luahb_constant_t {
   const char *name;
@@ -35,6 +36,7 @@ int register_tag(lua_State *L);
 int register_script(lua_State *L);
 int register_direction(lua_State *L);
 int register_language(lua_State *L);
+int register_variation(lua_State *L);
 int register_ot(lua_State *L);
 int register_unicode(lua_State *L);
 
diff --git a/source/texk/web2c/luatexdir/luaharfbuzz/src/luaharfbuzz/variation.c b/source/texk/web2c/luatexdir/luaharfbuzz/src/luaharfbuzz/variation.c
new file mode 100644
index 000000000..5683aa607
--- /dev/null
+++ b/source/texk/web2c/luatexdir/luaharfbuzz/src/luaharfbuzz/variation.c
@@ -0,0 +1,82 @@
+// harfbuzz.Variation
+#include "luaharfbuzz.h"
+
+static int variation_new(lua_State *L) {
+  Variation v;
+  const char *variation = luaL_checkstring(L, 1);
+
+  if (hb_variation_from_string(variation, -1, &v)) {
+    Variation *vp = (Variation *)lua_newuserdata(L, sizeof(*vp));
+    luaL_getmetatable(L, "harfbuzz.Variation");
+    lua_setmetatable(L, -2);
+    *vp = v;
+  } else {
+    lua_pushnil(L);
+  }
+
+  return 1;
+}
+
+static int variation_to_string(lua_State *L) {
+  Variation* v = (Variation *)luaL_checkudata(L, 1, "harfbuzz.Variation");
+  char variation[128];
+
+  hb_variation_to_string(v, variation, 128);
+  lua_pushstring(L, variation);
+  return 1;
+}
+
+static const char *variation_tag_ptr;
+static const char *variation_value_ptr;
+
+static int variation_index(lua_State *L) {
+  Variation* v = (Variation *)luaL_checkudata(L, 1, "harfbuzz.Variation");
+  const char *key = lua_tostring(L, 2);
+
+  if (key == variation_tag_ptr) {
+    Tag *tag = (Tag *)lua_newuserdata(L, sizeof(*tag));
+    luaL_getmetatable(L, "harfbuzz.Tag");
+    lua_setmetatable(L, -2);
+    *tag = v->tag;
+  } else if (key == variation_value_ptr) {
+    lua_pushnumber(L, v->value);
+  } else {
+    lua_pushnil(L);
+  }
+  return 1;
+}
+
+static int variation_newindex(lua_State *L) {
+  Variation* v = (Variation *)luaL_checkudata(L, 1, "harfbuzz.Variation");
+  const char *key = lua_tostring(L, 2);
+
+  if (key == variation_tag_ptr) {
+    v->tag = *(Tag *)luaL_checkudata(L, 3, "harfbuzz.Tag");
+  } else if (key == variation_value_ptr) {
+    v->value = luaL_checknumber(L, 3);
+  }
+  return 0;
+}
+
+static const struct luaL_Reg variation_methods[] = {
+  { "__index", variation_index },
+  { "__newindex", variation_newindex },
+  { "__tostring", variation_to_string },
+  { NULL, NULL },
+};
+
+static const struct luaL_Reg variation_functions[] = {
+  { "new", variation_new },
+  { NULL,  NULL }
+};
+
+int register_variation(lua_State *L) {
+  lua_pushliteral(L, "tag");
+  variation_tag_ptr = lua_tostring(L, -1);
+  (void) luaL_ref (L, LUA_REGISTRYINDEX);
+  lua_pushliteral(L, "value");
+  variation_value_ptr = lua_tostring(L, -1);
+  (void) luaL_ref (L, LUA_REGISTRYINDEX);
+
+  return register_class(L, "harfbuzz.Variation", variation_methods, variation_functions, NULL);
+}
-- 
2.32.0



More information about the dev-luatex mailing list