summaryrefslogtreecommitdiff
path: root/source/luametatex/source/luaoptional/lmtzint.c
diff options
context:
space:
mode:
Diffstat (limited to 'source/luametatex/source/luaoptional/lmtzint.c')
-rw-r--r--source/luametatex/source/luaoptional/lmtzint.c518
1 files changed, 518 insertions, 0 deletions
diff --git a/source/luametatex/source/luaoptional/lmtzint.c b/source/luametatex/source/luaoptional/lmtzint.c
new file mode 100644
index 000000000..0783238c0
--- /dev/null
+++ b/source/luametatex/source/luaoptional/lmtzint.c
@@ -0,0 +1,518 @@
+/*
+ See license.txt in the root of this project.
+*/
+
+/*
+ For a long time the zint api was quite stable but in after 2020 it started changing: the data
+ structures got fields added in the middle So, after a few updates Michal Vlasák suggested that
+ we adapt to versions. We can always decide to drop older ones when we get too many. The next
+ variant is a mix of our attempts to deal with this issue.
+
+*/
+
+# include "luametatex.h"
+# include "lmtoptional.h"
+
+# define ZINT_UNICODE_MODE 1
+# define ZINT_OUT_BUFFER 0
+# define ZINT_DM_SQUARE 100
+
+struct zint_vector;
+
+typedef struct {
+ int symbology;
+ float height;
+ int whitespace_width;
+ int whitespace_height;
+ int border_width;
+ int output_options;
+ char fgcolour[10];
+ char bgcolour[10];
+ char *fgcolor;
+ char *bgcolor;
+ char outfile[256];
+ float scale;
+ int option_1;
+ int option_2;
+ int option_3;
+ int show_hrt;
+ int fontsize;
+ int input_mode;
+ int eci;
+ unsigned char text[128];
+ int rows;
+ int width;
+ char primary[128];
+ unsigned char encoded_data[200][143];
+ float row_height[200];
+ char errtxt[100];
+ unsigned char *bitmap;
+ int bitmap_width;
+ int bitmap_height;
+ unsigned char *alphamap;
+ unsigned int bitmap_byte_length;
+ float dot_size;
+ struct zint_vector *vector;
+ int debug;
+ int warn_level;
+} zint_symbol_210;
+
+struct zint_structapp {
+ int index;
+ int count;
+ char id[32];
+};
+
+typedef struct {
+ int symbology;
+ float height;
+ float scale;
+ int whitespace_width;
+ int whitespace_height;
+ int border_width;
+ int output_options;
+ char fgcolour[10];
+ char bgcolour[10];
+ char *fgcolor;
+ char *bgcolor;
+ char outfile[256];
+ char primary[128];
+ int option_1;
+ int option_2;
+ int option_3;
+ int show_hrt;
+ int fontsize;
+ int input_mode;
+ int eci;
+ float dot_size;
+ float guard_descent;
+ struct zint_structapp structapp;
+ int warn_level;
+ int debug;
+ unsigned char text[128];
+ int rows;
+ int width;
+ unsigned char encoded_data[200][144];
+ float row_height[200];
+ char errtxt[100];
+ unsigned char *bitmap;
+ int bitmap_width;
+ int bitmap_height;
+ unsigned char *alphamap;
+ unsigned int bitmap_byte_length;
+ struct zint_vector *vector;
+} zint_symbol_211;
+
+
+typedef struct zint_rectangle zint_rectangle;
+
+typedef struct {
+ double x;
+ double y;
+ double w;
+ double h;
+ zint_rectangle *next;
+} lmt_zint_rectangle;
+
+static void lmt_zint_get_rect(
+ zint_rectangle *zint_,
+ lmt_zint_rectangle *lmt
+)
+{
+ struct {
+ float x;
+ float y;
+ float height;
+ float width;
+ int colour;
+ zint_rectangle *next;
+ } *zint = (void*) zint_;
+ lmt->x = (double) zint->x;
+ lmt->y = (double) zint->y;
+ lmt->w = (double) zint->width;
+ lmt->h = (double) zint->height;
+ lmt->next = zint->next;
+}
+
+typedef struct zint_circle zint_circle;
+
+typedef struct {
+ double x;
+ double y;
+ double d;
+ zint_circle *next;
+} lmt_zint_circle;
+
+static void lmt_zint_get_circle_210
+(
+ zint_circle *zint_,
+ lmt_zint_circle *lmt
+)
+{
+ struct {
+ float x;
+ float y;
+ float diameter;
+ int colour;
+ zint_circle *next;
+ } *zint = (void*) zint_;
+ lmt->x = (double) zint->x;
+ lmt->y = (double) zint->y;
+ lmt->d = (double) zint->diameter;
+ lmt->next = zint->next;
+}
+
+static void lmt_zint_get_circle_211
+(
+ zint_circle *zint_,
+ lmt_zint_circle *lmt
+)
+{
+ struct {
+ float x;
+ float y;
+ float diameter;
+ float width;
+ int colour;
+ zint_circle *next;
+ } *zint = (void*) zint_;
+ lmt->x = (double) zint->x;
+ lmt->y = (double) zint->y;
+ lmt->d = (double) zint->diameter;
+ lmt->next = zint->next;
+}
+
+typedef struct zint_hexagon zint_hexagon;
+
+typedef struct {
+ double x;
+ double y;
+ double d;
+ zint_hexagon *next;
+} lmt_zint_hexagon;
+
+static void lmt_zint_get_hexagon
+(
+ zint_hexagon *zint_,
+ lmt_zint_hexagon *lmt
+)
+{
+ struct {
+ float x;
+ float y;
+ float diameter;
+ int rotation;
+ zint_hexagon *next;
+ } *zint = (void *) zint_;
+ lmt->x = (double) zint->x;
+ lmt->y = (double) zint->y;
+ lmt->d = (double) zint->diameter;
+ lmt->next = zint->next;
+}
+
+typedef struct zint_string zint_string;
+
+typedef struct {
+ double x;
+ double y;
+ double s;
+ const char *t;
+ zint_string *next;
+} lmt_zint_string;
+
+static void lmt_zint_next_string(zint_string *zint_, lmt_zint_string *lmt)
+{
+ struct {
+ float x;
+ float y;
+ float fsize;
+ float width;
+ int length;
+ int rotation;
+ int halign;
+ unsigned char *text;
+ zint_string *next;
+ } *zint = (void *) zint_;
+ lmt->x = (double) zint->x;
+ lmt->y = (double) zint->y;
+ lmt->s = (double) zint->fsize;
+ lmt->t = (const char *) zint->text;
+ lmt->next = zint->next;
+}
+
+typedef struct zint_symbol zint_symbol;
+
+typedef struct zint_vector {
+ float width;
+ float height;
+ zint_rectangle *rectangles;
+ zint_hexagon *hexagons;
+ zint_string *strings;
+ zint_circle *circles;
+} zint_vector;
+
+static zint_vector *lmt_zint_vector_210(zint_symbol *symbol_)
+{
+ zint_symbol_210 *symbol = (void*) symbol_;
+ return symbol->vector;
+}
+
+static zint_vector *lmt_zint_vector_211(zint_symbol *symbol_)
+{
+ zint_symbol_211 *symbol = (void*) symbol_;
+ return symbol->vector;
+}
+
+static void lmt_zint_symbol_set_options_210(zint_symbol *symbol_, int symbology, int input_mode, int output_options, int square)
+{
+ zint_symbol_210 *symbol = (void*) symbol_;
+ symbol->symbology = symbology;
+ symbol->input_mode = input_mode;
+ symbol->output_options = output_options;
+ if (square)
+ symbol->option_3 = ZINT_DM_SQUARE;
+}
+
+static void lmt_zint_symbol_set_options_211(zint_symbol *symbol_, int symbology, int input_mode, int output_options, int square)
+{
+ zint_symbol_211 *symbol = (void*) symbol_;
+ symbol->symbology = symbology;
+ symbol->input_mode = input_mode;
+ symbol->output_options = output_options;
+ if (square) {
+ symbol->option_3 = ZINT_DM_SQUARE;
+ }
+}
+
+typedef struct zintlib_state_info {
+
+ int initialized;
+ int version;
+
+ int (*ZBarcode_Version) (
+ void
+ );
+
+ zint_symbol * (*ZBarcode_Create) (
+ void
+ );
+
+ void (*ZBarcode_Delete) (
+ zint_symbol *symbol
+ );
+
+ int (*ZBarcode_Encode_and_Buffer_Vector) (
+ zint_symbol *symbol,
+ const unsigned char *input,
+ int length,
+ int rotate_angle
+ );
+
+} zintlib_state_info;
+
+static zintlib_state_info zintlib_state = {
+
+ .initialized = 0,
+ .version = 0,
+
+ .ZBarcode_Version = NULL,
+ .ZBarcode_Create = NULL,
+ .ZBarcode_Delete = NULL,
+ .ZBarcode_Encode_and_Buffer_Vector = NULL,
+
+};
+
+static void (*lmt_zint_get_circle) (
+ zint_circle *zint_,
+ lmt_zint_circle *lmt
+);
+
+static zint_vector *(*lmt_zint_vector)(
+ zint_symbol *symbol_
+);
+static void (*lmt_zint_symbol_set_options)(
+ zint_symbol *symbol,
+ int symbology,
+ int input_mode,
+ int output_options,
+ int square
+);
+
+static int zintlib_initialize(lua_State * L)
+{
+ if (! zintlib_state.initialized) {
+ const char *filename = lua_tostring(L, 1);
+ if (filename) {
+
+ lmt_library lib = lmt_library_load(filename);
+
+ zintlib_state.ZBarcode_Version = lmt_library_find(lib, "ZBarcode_Version");
+ zintlib_state.ZBarcode_Create = lmt_library_find(lib, "ZBarcode_Create");
+ zintlib_state.ZBarcode_Delete = lmt_library_find(lib, "ZBarcode_Delete");
+ zintlib_state.ZBarcode_Encode_and_Buffer_Vector = lmt_library_find(lib, "ZBarcode_Encode_and_Buffer_Vector");
+
+ zintlib_state.initialized = lmt_library_okay(lib);
+
+ if (zintlib_state.ZBarcode_Version) {
+ zintlib_state.version = zintlib_state.ZBarcode_Version();
+ }
+ zintlib_state.version = zintlib_state.version / 100;
+ if (zintlib_state.version < 210) {
+ zintlib_state.initialized = 0;
+ } else if (zintlib_state.version < 211) {
+ lmt_zint_get_circle = lmt_zint_get_circle_210;
+ lmt_zint_vector = lmt_zint_vector_210;
+ lmt_zint_symbol_set_options = lmt_zint_symbol_set_options_210;
+ } else {
+ lmt_zint_get_circle = lmt_zint_get_circle_211;
+ lmt_zint_vector = lmt_zint_vector_211;
+ lmt_zint_symbol_set_options = lmt_zint_symbol_set_options_211;
+ }
+ }
+ }
+ lua_pushboolean(L, zintlib_state.initialized);
+ return 1;
+}
+
+static int zintlib_execute(lua_State * L)
+{
+ if (zintlib_state.initialized) {
+ if (lua_type(L, 1) == LUA_TTABLE) {
+ int code = -1;
+ size_t l = 0;
+ const unsigned char *s = NULL;
+ const char *o = NULL;
+ if (lua_getfield(L, 1, "code") == LUA_TNUMBER) {
+ code = lmt_tointeger(L, -1);
+ }
+ lua_pop(L, 1);
+ switch (lua_getfield(L, 1, "text")) {
+ case LUA_TSTRING:
+ case LUA_TNUMBER:
+ s = (const unsigned char *) lua_tolstring(L, -1, &l);
+ break;
+ }
+ lua_pop(L, 1);
+ if (lua_getfield(L, 1, "option") == LUA_TSTRING) {
+ /* for the moment one option */
+ o = lua_tostring(L, -1);
+ }
+ lua_pop(L, 1);
+ if (code >= 0 && l > 0) {
+ zint_symbol *symbol = zintlib_state.ZBarcode_Create();
+ if (symbol) {
+ /*tex
+ We could handle this at the \LUA\ end but as we only have a few options we
+ do it here.
+ */
+ int square = (o && (strcmp(o, "square") == 0)) ? 1 : 0;
+ lmt_zint_symbol_set_options(symbol, code, ZINT_UNICODE_MODE, ZINT_OUT_BUFFER, square);
+ if (zintlib_state.ZBarcode_Encode_and_Buffer_Vector(symbol, s, (int) l, 0)) {
+ zintlib_state.ZBarcode_Delete(symbol);
+ lua_pushboolean(L, 0);
+ lua_pushstring(L, "invalid result");
+ } else {
+ zint_vector *vector = lmt_zint_vector(symbol);
+ if (vector) {
+ /*tex
+ It's a bit like the svg output ... first I used named fields but a
+ list is more efficient, not so much in the \LUA\ interfacing but in
+ generating an compact path at the \METAPOST\ end.
+ */
+ lua_createtable(L, 0, 4);
+ if (vector->rectangles) {
+ lmt_zint_rectangle rectangle;
+ int i = 1;
+ lua_newtable(L);
+ for (zint_rectangle *r = vector->rectangles; r; r = rectangle.next) {
+ lmt_zint_get_rect(r, &rectangle);
+ lua_createtable(L, 4, 0);
+ lua_pushinteger(L, lmt_roundedfloat(rectangle.x)); lua_rawseti(L, -2, 1);
+ lua_pushinteger(L, lmt_roundedfloat(rectangle.y)); lua_rawseti(L, -2, 2);
+ lua_pushinteger(L, lmt_roundedfloat(rectangle.w)); lua_rawseti(L, -2, 3);
+ lua_pushinteger(L, lmt_roundedfloat(rectangle.h)); lua_rawseti(L, -2, 4);
+ lua_rawseti(L, -2, i++);
+ }
+ lua_setfield(L, -2, "rectangles");
+ }
+ if (vector->hexagons) {
+ lmt_zint_hexagon hexagon;
+ int i = 1;
+ lua_newtable(L);
+ for (zint_hexagon *h = vector->hexagons; h; h = hexagon.next) {
+ lmt_zint_get_hexagon(h, &hexagon);
+ lua_createtable(L, 0, 3);
+ lua_pushinteger(L, lmt_roundedfloat(hexagon.x)); lua_rawseti(L, -2, 1);
+ lua_pushinteger(L, lmt_roundedfloat(hexagon.y)); lua_rawseti(L, -2, 2);
+ lua_pushinteger(L, lmt_roundedfloat(hexagon.d)); lua_rawseti(L, -2, 3);
+ lua_rawseti(L, -2, i++);
+ }
+ lua_setfield(L, -2, "hexagons");
+ }
+ if (vector->circles) {
+ lmt_zint_circle circle;
+ int i = 1;
+ lua_newtable(L);
+ for (zint_circle *c = vector->circles; c; c = circle.next) {
+ lmt_zint_get_circle(c, &circle);
+ lua_createtable(L, 0, 3);
+ lua_pushinteger(L, lmt_roundedfloat(circle.x)); lua_rawseti(L, -2, 1);
+ lua_pushinteger(L, lmt_roundedfloat(circle.y)); lua_rawseti(L, -2, 2);
+ lua_pushinteger(L, lmt_roundedfloat(circle.d)); lua_rawseti(L, -2, 3);
+ lua_rawseti(L, -2, i++);
+ }
+ lua_setfield(L, -2, "circles");
+ }
+ if (vector->strings) {
+ lmt_zint_string string;
+ int i = 1;
+ lua_newtable(L);
+ for (zint_string *s = vector->strings; s; s = string.next) {
+ lmt_zint_next_string(s, &string);
+ lua_createtable(L, 0, 4);
+ lua_pushinteger(L, lmt_roundedfloat(string.x)); lua_rawseti(L, -2, 1);
+ lua_pushinteger(L, lmt_roundedfloat(string.y)); lua_rawseti(L, -2, 2);
+ lua_pushinteger(L, lmt_roundedfloat(string.s)); lua_rawseti(L, -2, 3);
+ lua_pushstring (L, string.t ); lua_rawseti(L, -2, 4);
+ lua_rawseti(L, -2, i++);
+ }
+ lua_setfield(L, -2, "strings");
+ }
+ zintlib_state.ZBarcode_Delete(symbol);
+ return 1;
+ } else {
+ zintlib_state.ZBarcode_Delete(symbol);
+ lua_pushboolean(L, 0);
+ lua_pushstring(L, "invalid result vector");
+ }
+ }
+ } else {
+ lua_pushboolean(L, 0);
+ lua_pushstring(L, "invalid result symbol");
+ }
+ } else {
+ lua_pushboolean(L, 0);
+ lua_pushstring(L, "invalid code");
+ }
+ } else {
+ lua_pushboolean(L, 0);
+ lua_pushstring(L, "invalid specification");
+ }
+ } else {
+ lua_pushboolean(L, 0);
+ lua_pushstring(L, "not initialized");
+ }
+ return 2;
+}
+
+static struct luaL_Reg zintlib_function_list[] = {
+ { "initialize", zintlib_initialize },
+ { "execute", zintlib_execute },
+ { NULL, NULL },
+};
+
+int luaopen_zint(lua_State * L)
+{
+ lmt_library_register(L, "zint", zintlib_function_list);
+ return 0;
+}