1
4
5# include "luametatex.h"
6# include "lmtoptional.h"
7
8
52
53typedef struct hb_blob_t hb_blob_t;
54
55
56
57typedef enum hb_memory_mode_t {
58 HB_MEMORY_MODE_DUPLICATE,
59 HB_MEMORY_MODE_READONLY,
60 HB_MEMORY_MODE_WRITABLE,
61 HB_MEMORY_MODE_READONLY_MAY_MAKE_WRITABLE
62} hb_memory_mode_t;
63
64typedef void (*hb_destroy_func_t) (
65 void *user_data
66);
67
68typedef struct hb_face_t hb_face_t;
69typedef const struct hb_language_impl_t *hb_language_t;
70typedef struct hb_buffer_t hb_buffer_t;
71
72
73
74
75
79
80typedef enum hb_script_t {
81 HB_SCRIPT_COMMON, HB_SCRIPT_INHERITED, HB_SCRIPT_UNKNOWN,
82
83 HB_SCRIPT_ARABIC, HB_SCRIPT_ARMENIAN, HB_SCRIPT_BENGALI, HB_SCRIPT_CYRILLIC,
84 HB_SCRIPT_DEVANAGARI, HB_SCRIPT_GEORGIAN, HB_SCRIPT_GREEK,
85 HB_SCRIPT_GUJARATI, HB_SCRIPT_GURMUKHI, HB_SCRIPT_HANGUL, HB_SCRIPT_HAN,
86 HB_SCRIPT_HEBREW, HB_SCRIPT_HIRAGANA, HB_SCRIPT_KANNADA, HB_SCRIPT_KATAKANA,
87 HB_SCRIPT_LAO, HB_SCRIPT_LATIN, HB_SCRIPT_MALAYALAM, HB_SCRIPT_ORIYA,
88 HB_SCRIPT_TAMIL, HB_SCRIPT_TELUGU, HB_SCRIPT_THAI, HB_SCRIPT_TIBETAN,
89 HB_SCRIPT_BOPOMOFO, HB_SCRIPT_BRAILLE, HB_SCRIPT_CANADIAN_SYLLABICS,
90 HB_SCRIPT_CHEROKEE, HB_SCRIPT_ETHIOPIC, HB_SCRIPT_KHMER, HB_SCRIPT_MONGOLIAN,
91 HB_SCRIPT_MYANMAR, HB_SCRIPT_OGHAM, HB_SCRIPT_RUNIC, HB_SCRIPT_SINHALA,
92 HB_SCRIPT_SYRIAC, HB_SCRIPT_THAANA, HB_SCRIPT_YI, HB_SCRIPT_DESERET,
93 HB_SCRIPT_GOTHIC, HB_SCRIPT_OLD_ITALIC, HB_SCRIPT_BUHID, HB_SCRIPT_HANUNOO,
94 HB_SCRIPT_TAGALOG, HB_SCRIPT_TAGBANWA, HB_SCRIPT_CYPRIOT, HB_SCRIPT_LIMBU,
95 HB_SCRIPT_LINEAR_B, HB_SCRIPT_OSMANYA, HB_SCRIPT_SHAVIAN, HB_SCRIPT_TAI_LE,
96 HB_SCRIPT_UGARITIC, HB_SCRIPT_BUGINESE, HB_SCRIPT_COPTIC,
97 HB_SCRIPT_GLAGOLITIC, HB_SCRIPT_KHAROSHTHI, HB_SCRIPT_NEW_TAI_LUE,
98 HB_SCRIPT_OLD_PERSIAN, HB_SCRIPT_SYLOTI_NAGRI, HB_SCRIPT_TIFINAGH,
99 HB_SCRIPT_BALINESE, HB_SCRIPT_CUNEIFORM, HB_SCRIPT_NKO, HB_SCRIPT_PHAGS_PA,
100 HB_SCRIPT_PHOENICIAN, HB_SCRIPT_CARIAN, HB_SCRIPT_CHAM, HB_SCRIPT_KAYAH_LI,
101 HB_SCRIPT_LEPCHA, HB_SCRIPT_LYCIAN, HB_SCRIPT_LYDIAN, HB_SCRIPT_OL_CHIKI,
102 HB_SCRIPT_REJANG, HB_SCRIPT_SAURASHTRA, HB_SCRIPT_SUNDANESE, HB_SCRIPT_VAI,
103 HB_SCRIPT_AVESTAN, HB_SCRIPT_BAMUM, HB_SCRIPT_EGYPTIAN_HIEROGLYPHS,
104 HB_SCRIPT_IMPERIAL_ARAMAIC, HB_SCRIPT_INSCRIPTIONAL_PAHLAVI,
105 HB_SCRIPT_INSCRIPTIONAL_PARTHIAN, HB_SCRIPT_JAVANESE, HB_SCRIPT_KAITHI,
106 HB_SCRIPT_LISU, HB_SCRIPT_MEETEI_MAYEK, HB_SCRIPT_OLD_SOUTH_ARABIAN,
107 HB_SCRIPT_OLD_TURKIC, HB_SCRIPT_SAMARITAN, HB_SCRIPT_TAI_THAM,
108 HB_SCRIPT_TAI_VIET, HB_SCRIPT_BATAK, HB_SCRIPT_BRAHMI, HB_SCRIPT_MANDAIC,
109 HB_SCRIPT_CHAKMA, HB_SCRIPT_MEROITIC_CURSIVE, HB_SCRIPT_MEROITIC_HIEROGLYPHS,
110 HB_SCRIPT_MIAO, HB_SCRIPT_SHARADA, HB_SCRIPT_SORA_SOMPENG, HB_SCRIPT_TAKRI,
111 HB_SCRIPT_BASSA_VAH, HB_SCRIPT_CAUCASIAN_ALBANIAN, HB_SCRIPT_DUPLOYAN,
112 HB_SCRIPT_ELBASAN, HB_SCRIPT_GRANTHA, HB_SCRIPT_KHOJKI, HB_SCRIPT_KHUDAWADI,
113 HB_SCRIPT_LINEAR_A, HB_SCRIPT_MAHAJANI, HB_SCRIPT_MANICHAEAN,
114 HB_SCRIPT_MENDE_KIKAKUI, HB_SCRIPT_MODI, HB_SCRIPT_MRO, HB_SCRIPT_NABATAEAN,
115 HB_SCRIPT_OLD_NORTH_ARABIAN, HB_SCRIPT_OLD_PERMIC, HB_SCRIPT_PAHAWH_HMONG,
116 HB_SCRIPT_PALMYRENE, HB_SCRIPT_PAU_CIN_HAU, HB_SCRIPT_PSALTER_PAHLAVI,
117 HB_SCRIPT_SIDDHAM, HB_SCRIPT_TIRHUTA, HB_SCRIPT_WARANG_CITI, HB_SCRIPT_AHOM,
118 HB_SCRIPT_ANATOLIAN_HIEROGLYPHS, HB_SCRIPT_HATRAN, HB_SCRIPT_MULTANI,
119 HB_SCRIPT_OLD_HUNGARIAN, HB_SCRIPT_SIGNWRITING, HB_SCRIPT_ADLAM,
120 HB_SCRIPT_BHAIKSUKI, HB_SCRIPT_MARCHEN, HB_SCRIPT_OSAGE, HB_SCRIPT_TANGUT,
121 HB_SCRIPT_NEWA, HB_SCRIPT_MASARAM_GONDI, HB_SCRIPT_NUSHU, HB_SCRIPT_SOYOMBO,
122 HB_SCRIPT_ZANABAZAR_SQUARE, HB_SCRIPT_DOGRA, HB_SCRIPT_GUNJALA_GONDI,
123 HB_SCRIPT_HANIFI_ROHINGYA, HB_SCRIPT_MAKASAR, HB_SCRIPT_MEDEFAIDRIN,
124 HB_SCRIPT_OLD_SOGDIAN, HB_SCRIPT_SOGDIAN, HB_SCRIPT_ELYMAIC,
125 HB_SCRIPT_NANDINAGARI, HB_SCRIPT_NYIAKENG_PUACHUE_HMONG, HB_SCRIPT_WANCHO,
126
127 HB_SCRIPT_INVALID, _HB_SCRIPT_MAX_VALUE, _HB_SCRIPT_MAX_VALUE_SIGNED,
128} hb_script_t;
129
130typedef enum hb_direction_t {
131 HB_DIRECTION_INVALID,
132 HB_DIRECTION_LTR,
133 HB_DIRECTION_RTL,
134 HB_DIRECTION_TTB,
135 HB_DIRECTION_BTT
136} hb_direction_t;
137
138typedef int hb_bool_t;
139
140typedef uint32_t hb_tag_t;
141
142typedef struct hb_feature_t {
143 hb_tag_t tag;
144 uint32_t value;
145 unsigned int start;
146 unsigned int end;
147} hb_feature_t;
148
149typedef struct hb_font_t hb_font_t;
150
151typedef uint32_t hb_codepoint_t;
152typedef int32_t hb_position_t;
153typedef uint32_t hb_mask_t;
154
155typedef union _hb_var_int_t {
156 uint32_t u32;
157 int32_t i32;
158 uint16_t u16[2];
159 int16_t i16[2];
160 uint8_t u8[4];
161 int8_t i8[4];
162} hb_var_int_t;
163
164typedef struct hb_glyph_info_t {
165 hb_codepoint_t codepoint;
166 hb_mask_t mask;
167 uint32_t cluster;
168
169 hb_var_int_t var1;
170 hb_var_int_t var2;
171} hb_glyph_info_t;
172
173typedef struct hb_glyph_position_t {
174 hb_position_t x_advance;
175 hb_position_t y_advance;
176 hb_position_t x_offset;
177 hb_position_t y_offset;
178
179 hb_var_int_t var;
180} hb_glyph_position_t;
181
182
195
196# define HBLIB_METATABLE "optional.hblib"
197
198typedef struct hblib_data {
199 hb_font_t *font;
200} hblib_data;
201
202typedef struct hblib_state_info {
203
204 int initialized;
205 int padding;
206
207 const char * (*hb_version_string) (
208 void
209 );
210
211 hb_blob_t * (*hb_blob_create) (
212 const char *data,
213 unsigned int length,
214 hb_memory_mode_t mode,
215 void *user_data,
216 hb_destroy_func_t destroy
217 );
218
219 void (*hb_blob_destroy) (
220 hb_blob_t *blob
221 );
222
223 hb_face_t * (*hb_face_create) (
224 hb_blob_t *blob,
225 unsigned int index
226 );
227
228 void (*hb_face_destroy) (
229 hb_face_t *face
230 );
231
232 hb_language_t (*hb_language_from_string) (
233 const char *str,
234 int len
235 );
236
237 void (*hb_buffer_set_language) (
238 hb_buffer_t *buffer,
239 hb_language_t language
240 );
241
242 hb_script_t (*hb_script_from_string) (
243 const char *s,
244 int len
245 );
246
247 void (*hb_buffer_set_script) (
248 hb_buffer_t *buffer,
249 hb_script_t script
250 );
251
252 hb_direction_t (*hb_direction_from_string) (
253 const char *str,
254 int len
255 );
256
257 void (*hb_buffer_set_direction) (
258 hb_buffer_t *buffer,
259 hb_direction_t direction
260 );
261
262 hb_bool_t (*hb_feature_from_string) (
263 const char *str,
264 int len,
265 hb_feature_t *feature
266 );
267
268 hb_bool_t (*hb_shape_full) (
269 hb_font_t *font,
270 hb_buffer_t *buffer,
271 const hb_feature_t *features,
272 unsigned int num_features,
273 const char * const *shaper_list
274 );
275
276 hb_buffer_t * (*hb_buffer_create )(
277 void
278 );
279
280 void (*hb_buffer_destroy)(
281 hb_buffer_t *buffer
282 );
283
284 void (*hb_buffer_add_utf8) (
285 hb_buffer_t *buffer,
286 const char *text,
287 int text_length,
288 unsigned int item_offset,
289 int item_length
290 );
291
292 void (*hb_buffer_add_utf32) (
293 hb_buffer_t *buffer,
294 const char *text,
295 int text_length,
296 unsigned int item_offset,
297 int item_length
298 );
299
300
305
306 unsigned int (*hb_buffer_get_length) (
307 hb_buffer_t *buffer
308 );
309
310 hb_glyph_info_t * (*hb_buffer_get_glyph_infos) (
311 hb_buffer_t *buffer,
312 unsigned int *length
313 );
314
315 hb_glyph_position_t * (*hb_buffer_get_glyph_positions) (
316 hb_buffer_t *buffer,
317 unsigned int *length
318 );
319
320 void (*hb_buffer_reverse) (
321 hb_buffer_t *buffer
322 );
323
324 void (*hb_buffer_reset) (
325 hb_buffer_t *buffer
326 );
327
328 void (*hb_buffer_guess_segment_properties) (
329 hb_buffer_t *buffer
330 );
331
332 hb_font_t * (*hb_font_create) (
333 hb_face_t *face
334 );
335
336 void (*hb_font_destroy) (
337 hb_font_t *font
338 );
339
340 void (*hb_font_set_scale) (
341 hb_font_t *font,
342 int x_scale,
343 int y_scale
344 );
345
346 void (*hb_ot_font_set_funcs) (
347 hb_font_t *font
348 );
349
350 unsigned int (*hb_face_get_upem) (
351 hb_face_t *face
352 );
353
354 const char ** (*hb_shape_list_shapers) (
355 void
356 );
357
358} hblib_state_info;
359
360static hblib_state_info hblib_state = {
361
362 .initialized = 0,
363 .padding = 0,
364
365 .hb_version_string = NULL,
366 .hb_blob_create = NULL,
367 .hb_blob_destroy = NULL,
368 .hb_face_create = NULL,
369 .hb_face_destroy = NULL,
370 .hb_language_from_string = NULL,
371 .hb_buffer_set_language = NULL,
372 .hb_script_from_string = NULL,
373 .hb_buffer_set_script = NULL,
374 .hb_direction_from_string = NULL,
375 .hb_buffer_set_direction = NULL,
376 .hb_feature_from_string = NULL,
377 .hb_shape_full = NULL,
378 .hb_buffer_create = NULL,
379 .hb_buffer_destroy = NULL,
380 .hb_buffer_add_utf8 = NULL,
381 .hb_buffer_add_utf32 = NULL,
382
383 .hb_buffer_get_length = NULL,
384 .hb_buffer_get_glyph_infos = NULL,
385 .hb_buffer_get_glyph_positions = NULL,
386 .hb_buffer_reverse = NULL,
387 .hb_buffer_reset = NULL,
388 .hb_buffer_guess_segment_properties = NULL,
389 .hb_font_create = NULL,
390 .hb_font_destroy = NULL,
391 .hb_font_set_scale = NULL,
392 .hb_ot_font_set_funcs = NULL,
393 .hb_face_get_upem = NULL,
394 .hb_shape_list_shapers = NULL,
395
396};
397
398
399
400static int hblib_initialize(lua_State * L)
401{
402 if (! hblib_state.initialized) {
403 const char *filename = lua_tostring(L, 1);
404 if (filename) {
405
406 lmt_library lib = lmt_library_load(filename);
407
408 hblib_state.hb_version_string = lmt_library_find(lib, "hb_version_string");
409 hblib_state.hb_language_from_string = lmt_library_find(lib, "hb_language_from_string");
410 hblib_state.hb_script_from_string = lmt_library_find(lib, "hb_script_from_string");
411 hblib_state.hb_direction_from_string = lmt_library_find(lib, "hb_direction_from_string");
412 hblib_state.hb_feature_from_string = lmt_library_find(lib, "hb_feature_from_string");
413
414 hblib_state.hb_buffer_set_language = lmt_library_find(lib, "hb_buffer_set_language");
415 hblib_state.hb_buffer_set_script = lmt_library_find(lib, "hb_buffer_set_script");
416 hblib_state.hb_buffer_set_direction = lmt_library_find(lib, "hb_buffer_set_direction");
417
418 hblib_state.hb_buffer_create = lmt_library_find(lib, "hb_buffer_create");
419 hblib_state.hb_buffer_destroy = lmt_library_find(lib, "hb_buffer_destroy");
420 hblib_state.hb_buffer_reverse = lmt_library_find(lib, "hb_buffer_reverse");
421 hblib_state.hb_buffer_get_length = lmt_library_find(lib, "hb_buffer_get_length");
422 hblib_state.hb_buffer_reset = lmt_library_find(lib, "hb_buffer_reset");
423 hblib_state.hb_buffer_add_utf8 = lmt_library_find(lib, "hb_buffer_add_utf8");
424 hblib_state.hb_buffer_add_utf32 = lmt_library_find(lib, "hb_buffer_add_utf32");
425
426 hblib_state.hb_blob_create = lmt_library_find(lib, "hb_blob_create");
427 hblib_state.hb_blob_destroy = lmt_library_find(lib, "hb_blob_destroy");
428
429 hblib_state.hb_face_create = lmt_library_find(lib, "hb_face_create");
430 hblib_state.hb_face_destroy = lmt_library_find(lib, "hb_face_destroy");
431 hblib_state.hb_face_get_upem = lmt_library_find(lib, "hb_face_get_upem");
432
433 hblib_state.hb_font_create = lmt_library_find(lib, "hb_font_create");
434 hblib_state.hb_font_destroy = lmt_library_find(lib, "hb_font_destroy");
435 hblib_state.hb_font_set_scale = lmt_library_find(lib, "hb_font_set_scale");
436
437 hblib_state.hb_shape_list_shapers = lmt_library_find(lib, "hb_shape_list_shapers");
438 hblib_state.hb_shape_full = lmt_library_find(lib, "hb_shape_full");
439
440 hblib_state.hb_ot_font_set_funcs = lmt_library_find(lib, "hb_ot_font_set_funcs");
441
442 hblib_state.hb_buffer_guess_segment_properties = lmt_library_find(lib, "hb_buffer_guess_segment_properties");
443 hblib_state.hb_buffer_get_glyph_positions = lmt_library_find(lib, "hb_buffer_get_glyph_positions");
444 hblib_state.hb_buffer_get_glyph_infos = lmt_library_find(lib, "hb_buffer_get_glyph_infos");
445
446 hblib_state.initialized = lmt_library_okay(lib);
447 }
448 }
449 lua_pushboolean(L, hblib_state.initialized);
450 return 1;
451}
452
453
454
455static int hblib_get_version(lua_State * L)
456{
457 if (hblib_state.initialized) {
458 lua_pushstring(L, hblib_state.hb_version_string());
459 return 1;
460 } else {
461 return 0;
462 }
463}
464
465
466
467static int hblib_load_font(lua_State * L)
468{
469 if (hblib_state.initialized) {
470 int id = (int) lua_tointeger(L, 1);
471 const char *str= lua_tostring(L, 2);
472 int size = (int) lua_rawlen(L, 2);
473 hb_blob_t *blob = hblib_state.hb_blob_create(str, size, 0, NULL, NULL);
474 hb_face_t *face = hblib_state.hb_face_create(blob, id);
475 unsigned int scale = hblib_state.hb_face_get_upem(face);
476 hb_font_t *font = hblib_state.hb_font_create(face);
477 hblib_data *data = lua_newuserdatauv(L, sizeof(data), 0);
478 hblib_state.hb_font_set_scale(font, scale, scale);
479 hblib_state.hb_ot_font_set_funcs(font);
480 data->font = font;
481 luaL_getmetatable(L, HBLIB_METATABLE);
482 lua_setmetatable(L, -2);
483 hblib_state.hb_blob_destroy(blob);
484 hblib_state.hb_face_destroy(face);
485 return 1;
486 } else {
487 return 0;
488 }
489}
490
491
492
493static int hblib_utf8len(const char *text, size_t size)
494{
495 size_t ls = size;
496 int ind = 0;
497 int num = 0;
498 while (ind < (int) ls) {
499 unsigned char i = (unsigned char) *(text + ind);
500 if (i < 0x80) {
501 ind += 1;
502 } else if (i >= 0xF0) {
503 ind += 4;
504 } else if (i >= 0xE0) {
505 ind += 3;
506 } else if (i >= 0xC0) {
507 ind += 2;
508 } else {
509 ind += 1;
510 }
511 num += 1;
512 }
513 return num;
514}
515
516static int hblib_utf32len(const char *text, size_t size)
517{
518
519
520
521
522 size_t ls = size;
523 int ind = 0;
524 int num = 0;
525 while (ind < (int) ls) {
526 unsigned char i = (unsigned char) *(text + ind);
527 if (i) {
528 ind += 4;
529 } else {
530 break;
531 }
532 num += 1;
533 }
534 return num;
535}
536
537
547
548static int hblib_shape_string(lua_State * L)
549{
550 if (hblib_state.initialized) {
551 hblib_data *data = luaL_checkudata(L, 1, HBLIB_METATABLE);
552 if (data == NULL) {
553 lua_pushnil(L);
554 } else {
555
556 size_t nofscript = 0;
557 const char *script = lua_tolstring(L, 2, &nofscript);
558 size_t noflanguage = 0;
559 const char *language = lua_tolstring(L, 3, &noflanguage);
560 size_t nofdirection = 0;
561 const char *direction = lua_tolstring(L, 4, &nofdirection);
562 int nofshapers = 0;
563 const char * *shapers = NULL;
564 int noffeatures = 0;
565 hb_feature_t *features = NULL;
566 size_t noftext = 0;
567 const char *text = lua_tolstring(L, 7, &noftext);
568 int reverse = lua_toboolean(L, 8);
569 int utfbits = (int) luaL_optinteger(L, 9, 8);
570 hb_buffer_t *buffer = NULL;
571
579 if (lua_istable(L, 5)) {
580 lua_Unsigned n = lua_rawlen(L, 5);
581 if (n > 0) {
582
583 shapers = calloc((size_t) (n + 1), sizeof(char *));
584 if (shapers) {
585 for (lua_Unsigned i = 0; i < n; i++) {
586 lua_rawgeti(L, 5, i + 1);
587 if (lua_isstring(L, -1)) {
588 shapers[nofshapers] = lua_tostring(L, -1);
589 nofshapers += 1;
590 }
591 lua_pop(L, 1);
592 }
593 } else {
594 luaL_error(L, "optional hblib: unable to allocate shaper memory");
595 }
596
597 shapers[nofshapers] = NULL;
598 }
599 }
600
604 if (lua_istable(L, 6)) {
605 lua_Unsigned n = lua_rawlen(L, 6);
606 if (n > 0) {
607 features = malloc((size_t) n * sizeof(hb_feature_t));
608 if (features) {
609 for (lua_Unsigned i = 0; i < n; i++) {
610 lua_rawgeti(L, 6, i + 1);
611 if (lua_isstring(L, -1)) {
612 size_t l = 0;
613 const char *s = lua_tolstring(L, -1, &l);
614 hblib_state.hb_feature_from_string(s, (int) l, &features[noffeatures]);
615 noffeatures += 1;
616 }
617 lua_pop(L, 1);
618 }
619 } else {
620 luaL_error(L, "optional hblib: unable to allocate feature memory");
621 }
622 }
623 }
624
625 buffer = hblib_state.hb_buffer_create();
626
630 if (utfbits == 32) {
631 hblib_state.hb_buffer_add_utf32(buffer, text, (int) noftext, 0, hblib_utf32len(text, noftext));
632 } else {
633 hblib_state.hb_buffer_add_utf8(buffer, text, (int) noftext, 0, hblib_utf8len(text, noftext));
634 }
635 hblib_state.hb_buffer_set_language(buffer, hblib_state.hb_language_from_string(language, (int) noflanguage));
636 hblib_state.hb_buffer_set_script(buffer, hblib_state.hb_script_from_string(script, (int) nofscript));
637 hblib_state.hb_buffer_set_direction(buffer, hblib_state.hb_direction_from_string(direction, (int) nofdirection));
638 hblib_state.hb_buffer_guess_segment_properties(buffer);
639
640 hblib_state.hb_shape_full(data->font, buffer, features, noffeatures, shapers);
641
642 if (reverse) {
643 hblib_state.hb_buffer_reverse(buffer);
644 }
645
646 {
647 unsigned length = hblib_state.hb_buffer_get_length(buffer);
648 hb_glyph_info_t *infos = hblib_state.hb_buffer_get_glyph_infos(buffer, NULL);
649 hb_glyph_position_t *positions = hblib_state.hb_buffer_get_glyph_positions(buffer, NULL);
650 lua_createtable(L, length, 0);
651 for (unsigned i = 0; i < length; i++) {
652 lua_createtable(L, 6, 0);
653 lua_pushinteger(L, infos[i].codepoint);
654 lua_rawseti(L, -2, 1);
655 lua_pushinteger(L, infos[i].cluster);
656 lua_rawseti(L, -2, 2);
657 lua_pushinteger(L, positions[i].x_offset);
658 lua_rawseti(L, -2, 3);
659 lua_pushinteger(L, positions[i].y_offset);
660 lua_rawseti(L, -2, 4);
661 lua_pushinteger(L, positions[i].x_advance);
662 lua_rawseti(L, -2, 5);
663 lua_pushinteger(L, positions[i].y_advance);
664 lua_rawseti(L, -2, 6);
665 lua_rawseti(L, -2, (lua_Integer) i + 1);
666 }
667 }
668
672 hblib_state.hb_buffer_destroy(buffer);
673 free((void *) shapers);
674 free((void *) features);
675 }
676 return 1;
677 } else {
678 return 0;
679 }
680}
681
682
683
684static int hblib_get_shapers(lua_State * L)
685{
686 if (hblib_state.initialized) {
687 const char * *shapers = hblib_state.hb_shape_list_shapers();
688 if (shapers) {
689 int nofshapers = 0;
690 lua_createtable(L, 1, 0);
691 while (1) {
692 const char *s = shapers[nofshapers];
693 if (s) {
694 nofshapers++;
695 lua_pushstring(L, s);
696 lua_rawseti(L, -2, nofshapers);
697 } else {
698 break;
699 }
700 }
701 return 1;
702 }
703 }
704 return 0;
705}
706
707
708
709static int hblib_free(lua_State * L)
710{
711 if (hblib_state.initialized) {
712 hblib_data *data = luaL_checkudata(L, 1, HBLIB_METATABLE);
713 if (data) {
714 hblib_state.hb_font_destroy(data->font);
715 }
716 }
717 return 0;
718}
719
720
721
722static int hblib_tostring(lua_State * L)
723{
724 if (hblib_state.initialized) {
725 hblib_data *data = luaL_checkudata(L, 1, HBLIB_METATABLE);
726 if (data) {
727 lua_pushfstring(L, "<optional.hblib.instance %p>", data);
728 } else {
729 lua_pushnil(L);
730 }
731 return 1;
732 } else {
733 return 0;
734 }
735}
736
737
738
739static const struct luaL_Reg hblib_metatable[] = {
740 { "__tostring", hblib_tostring },
741 { "__gc", hblib_free },
742 { NULL, NULL },
743};
744
745
751
752static struct luaL_Reg hblib_function_list[] = {
753 { "initialize", hblib_initialize },
754 { "getversion", hblib_get_version },
755 { "getshapers", hblib_get_shapers },
756 { "loadfont", hblib_load_font },
757 { "shapestring", hblib_shape_string },
758 { NULL, NULL },
759};
760
761int luaopen_hb(lua_State *L)
762{
763 luaL_newmetatable(L, HBLIB_METATABLE);
764 luaL_setfuncs(L, hblib_metatable, 0);
765 lmt_library_register(L, "hb", hblib_function_list);
766 return 0;
767}
768 |