#include "hb-utils.h"
#include <string.h>
#include <stdlib.h>
#include <hb-ot.h>
#include "silewin32.h"
static hb_variation_t* scan_variation_string(const char* cp1, unsigned int* ret) {
hb_variation_t* variations = NULL;
hb_variation_t variation;
unsigned int nVariations = 0;
const char* cp2;
if (!cp1)
return NULL;
while (*cp1) {
if ((*cp1 == ':') || (*cp1 == ';') || (*cp1 == ','))
++cp1;
while ((*cp1 == ' ') || (*cp1 == '\t'))
++cp1;
if (*cp1 == 0)
break;
cp2 = cp1;
while (*cp2 && (*cp2 != ':') && (*cp2 != ';') && (*cp2 != ','))
++cp2;
if (hb_variation_from_string(cp1, cp2 - cp1, &variation)) {
variations = realloc(variations, (nVariations + 1) * sizeof(hb_variation_t));
variations[nVariations++] = variation;
}
cp1 = cp2;
}
*ret = nVariations;
return variations;
}
hb_font_t* get_hb_font(lua_State *L, int index) {
const char * filename;
int face_index = 0;
hb_blob_t* blob;
hb_face_t* face;
hb_font_t* font;
unsigned int upem;
luaL_checktype(L, index, LUA_TTABLE);
lua_getfield(L, index, "hbFont");
if (lua_islightuserdata(L, -1)) { return lua_touserdata(L, -1); }
lua_getfield(L, index, "filename");
filename = luaL_checkstring(L, -1);
lua_getfield(L, index, "index");
if (lua_isnumber(L, -1)) { face_index = lua_tointeger(L, -1); }
blob = hb_blob_create_from_file(filename);
face = hb_face_create(blob, face_index);
font = hb_font_create(face);
upem = hb_face_get_upem(face);
hb_font_set_scale(font, upem, upem);
hb_ot_font_set_funcs(font);
#ifdef HAVE_HARFBUZZ_SUBSET
if (hb_ot_var_has_data(face)) {
hb_ot_var_axis_info_t* axes;
unsigned int nAxes;
unsigned int nCoords;
const float* coords;
float* newCoords;
nAxes = hb_ot_var_get_axis_infos(face, 0, NULL, NULL);
axes = malloc(nAxes * sizeof(hb_ot_var_axis_info_t));
hb_ot_var_get_axis_infos(face, 0, &nAxes, axes);
coords = hb_font_get_var_coords_design(font, &nCoords);
newCoords = malloc(nAxes * sizeof(float));
for (unsigned i = 0; i < nAxes; i++) {
if (i < nCoords)
newCoords[i] = coords[i];
else
newCoords[i] = axes[i].default_value;
}
for (unsigned i = 0; i < nAxes; i++) {
switch (axes[i].tag) {
case HB_TAG('o', 'p', 's', 'z'):
lua_getfield(L, index, "pointsize");
if (lua_isnumber(L, -1)) { newCoords[i] = lua_tonumber(L, -1); }
break;
case HB_TAG('w', 'g', 'h', 't'):
lua_getfield(L, index, "weight");
if (lua_isnumber(L, -1)) { newCoords[i] = lua_tonumber(L, -1); }
break;
case HB_TAG('i', 't', 'a', 'l'):
lua_getfield(L, index, "style");
if (lua_isstring(L, -1)) {
const char* style = lua_tostring(L, -1);
if (!strcasecmp(style, "italic"))
newCoords[i] = 1;
}
break;
default: break;
}
}
lua_getfield(L, index, "variations");
if (lua_isstring(L, -1)) {
const char* variationstring = lua_tostring(L, -1);
unsigned int nVariations = 0;
hb_variation_t* variations = scan_variation_string(variationstring, &nVariations);
if (variations) {
for (unsigned nVariation = 0; nVariation < nVariations; nVariation++) {
for (unsigned nAxis = 0; nAxis < nAxes; nAxis++) {
if (variations[nVariation].tag == axes[nAxis].tag)
newCoords[nAxis] = variations[nVariation].value;
}
}
free(variations);
}
}
hb_font_set_var_coords_design(font, newCoords, nAxes);
free(axes);
free(newCoords);
}
#endif
hb_face_destroy(face);
hb_blob_destroy(blob);
lua_pushlightuserdata(L, font);
lua_setfield(L, index, "hbFont");
return font;
}