#ifdef SQ_USE_FREETYPE #include #include #include "squirrel.h" #include "sqstdblobimpl.h" #include #include FT_FREETYPE_H #include "dynamic_library.h" /*SquiLu local library_functions = [ ["FT_Error", "FT_Init_FreeType", "FT_Library *library"], ["FT_Error", "FT_New_Face", "FT_Library library, const char* filepathname, FT_Long face_index, FT_Face *aface"], ["FT_Error", "FT_New_Memory_Face", "FT_Library library, const FT_Byte* file_base, FT_Long file_size, FT_Long face_index, FT_Face *aface"], ["FT_Error", "FT_Done_Face", "FT_Face face"], ["FT_Error", "FT_Set_Char_Size", "FT_Face face, FT_F26Dot6 char_width, FT_F26Dot6 char_height, FT_UInt horz_resolution, FT_UInt vert_resolution"], ["FT_Error", "FT_Load_Glyph", "FT_Face face, FT_UInt glyph_index, FT_Int32 load_flags"], ["FT_Error", "FT_Load_Char", "FT_Face face, FT_ULong char_code, FT_Int32 load_flags"], ["FT_Error", "FT_Get_Glyph_Name", "FT_Face face, FT_UInt glyph_index, FT_Pointer buffer, FT_UInt buffer_max"], ["const char*", "FT_Get_Postscript_Name", "FT_Face face"], ["FT_Error", "FT_Select_Charmap", "FT_Face face, FT_Encoding encoding"], ["FT_Error", "FT_Set_Charmap", "FT_Face face, FT_CharMap charmap"], ["FT_Int", "FT_Get_Charmap_Index", "FT_CharMap charmap"], ["FT_UInt", "FT_Get_Char_Index", "FT_Face face, FT_ULong charcode"], ["FT_ULong", "FT_Get_First_Char", "FT_Face face, FT_UInt *agindex"], ["FT_ULong", "FT_Get_Next_Char", "FT_Face face, FT_ULong char_code, FT_UInt *agindex"], ["FT_UInt", "FT_Get_Name_Index", "FT_Face face, FT_String* glyph_name"], //next entry should be the last one //to make valid the test made on load_library function ["FT_Error", "FT_Done_FreeType", "FT_Library library"], ]; function write_library_functions_declaration(){ foreach(k,v in library_functions) { putsnl("typedef " + v[0] + " (*" + v[1] + "_t)(" + v[2] + ");"); putsnl("static " + v[1] + "_t dl" + v[1] + " = 0;"); } } function write_library_functions_load(){ foreach(k,v in library_functions){ putsnl("dl" + v[1] + " = (" + v[1] + "_t) libdyn.dlsym(\"" + v[1] + "\");"); putsnl("if(!dl" + v[1] + ") return false;"); } } function write_library_functions_static_defines(){ foreach(k,v in library_functions){ putsnl("#define dl" + v[1] + " " + v[1]); } } SquiLu*/ static DynamicLibrary libdyn; //@write_library_functions_declaration(); // generated-code:begin typedef FT_Error (*FT_Init_FreeType_t)(FT_Library *library); static FT_Init_FreeType_t dlFT_Init_FreeType = 0; typedef FT_Error (*FT_New_Face_t)(FT_Library library, const char* filepathname, FT_Long face_index, FT_Face *aface); static FT_New_Face_t dlFT_New_Face = 0; typedef FT_Error (*FT_New_Memory_Face_t)(FT_Library library, const FT_Byte* file_base, FT_Long file_size, FT_Long face_index, FT_Face *aface); static FT_New_Memory_Face_t dlFT_New_Memory_Face = 0; typedef FT_Error (*FT_Done_Face_t)(FT_Face face); static FT_Done_Face_t dlFT_Done_Face = 0; typedef FT_Error (*FT_Set_Char_Size_t)(FT_Face face, FT_F26Dot6 char_width, FT_F26Dot6 char_height, FT_UInt horz_resolution, FT_UInt vert_resolution); static FT_Set_Char_Size_t dlFT_Set_Char_Size = 0; typedef FT_Error (*FT_Load_Glyph_t)(FT_Face face, FT_UInt glyph_index, FT_Int32 load_flags); static FT_Load_Glyph_t dlFT_Load_Glyph = 0; typedef FT_Error (*FT_Load_Char_t)(FT_Face face, FT_ULong char_code, FT_Int32 load_flags); static FT_Load_Char_t dlFT_Load_Char = 0; typedef FT_Error (*FT_Get_Glyph_Name_t)(FT_Face face, FT_UInt glyph_index, FT_Pointer buffer, FT_UInt buffer_max); static FT_Get_Glyph_Name_t dlFT_Get_Glyph_Name = 0; typedef const char* (*FT_Get_Postscript_Name_t)(FT_Face face); static FT_Get_Postscript_Name_t dlFT_Get_Postscript_Name = 0; typedef FT_Error (*FT_Select_Charmap_t)(FT_Face face, FT_Encoding encoding); static FT_Select_Charmap_t dlFT_Select_Charmap = 0; typedef FT_Error (*FT_Set_Charmap_t)(FT_Face face, FT_CharMap charmap); static FT_Set_Charmap_t dlFT_Set_Charmap = 0; typedef FT_Int (*FT_Get_Charmap_Index_t)(FT_CharMap charmap); static FT_Get_Charmap_Index_t dlFT_Get_Charmap_Index = 0; typedef FT_UInt (*FT_Get_Char_Index_t)(FT_Face face, FT_ULong charcode); static FT_Get_Char_Index_t dlFT_Get_Char_Index = 0; typedef FT_ULong (*FT_Get_First_Char_t)(FT_Face face, FT_UInt *agindex); static FT_Get_First_Char_t dlFT_Get_First_Char = 0; typedef FT_ULong (*FT_Get_Next_Char_t)(FT_Face face, FT_ULong char_code, FT_UInt *agindex); static FT_Get_Next_Char_t dlFT_Get_Next_Char = 0; typedef FT_UInt (*FT_Get_Name_Index_t)(FT_Face face, FT_String* glyph_name); static FT_Get_Name_Index_t dlFT_Get_Name_Index = 0; typedef FT_Error (*FT_Done_FreeType_t)(FT_Library library); static FT_Done_FreeType_t dlFT_Done_FreeType = 0; // generated-code:end static const char *dynamicLibName = DYNLIB_FOR_OS(libfreetype); static bool load_library(const char *libname) { if(dlFT_Done_FreeType) return true; if(libdyn.open(libname)) { //@write_library_functions_load(); // generated-code:begin dlFT_Init_FreeType = (FT_Init_FreeType_t) libdyn.dlsym("FT_Init_FreeType"); if(!dlFT_Init_FreeType) return false; dlFT_New_Face = (FT_New_Face_t) libdyn.dlsym("FT_New_Face"); if(!dlFT_New_Face) return false; dlFT_New_Memory_Face = (FT_New_Memory_Face_t) libdyn.dlsym("FT_New_Memory_Face"); if(!dlFT_New_Memory_Face) return false; dlFT_Done_Face = (FT_Done_Face_t) libdyn.dlsym("FT_Done_Face"); if(!dlFT_Done_Face) return false; dlFT_Set_Char_Size = (FT_Set_Char_Size_t) libdyn.dlsym("FT_Set_Char_Size"); if(!dlFT_Set_Char_Size) return false; dlFT_Load_Glyph = (FT_Load_Glyph_t) libdyn.dlsym("FT_Load_Glyph"); if(!dlFT_Load_Glyph) return false; dlFT_Load_Char = (FT_Load_Char_t) libdyn.dlsym("FT_Load_Char"); if(!dlFT_Load_Char) return false; dlFT_Get_Glyph_Name = (FT_Get_Glyph_Name_t) libdyn.dlsym("FT_Get_Glyph_Name"); if(!dlFT_Get_Glyph_Name) return false; dlFT_Get_Postscript_Name = (FT_Get_Postscript_Name_t) libdyn.dlsym("FT_Get_Postscript_Name"); if(!dlFT_Get_Postscript_Name) return false; dlFT_Select_Charmap = (FT_Select_Charmap_t) libdyn.dlsym("FT_Select_Charmap"); if(!dlFT_Select_Charmap) return false; dlFT_Set_Charmap = (FT_Set_Charmap_t) libdyn.dlsym("FT_Set_Charmap"); if(!dlFT_Set_Charmap) return false; dlFT_Get_Charmap_Index = (FT_Get_Charmap_Index_t) libdyn.dlsym("FT_Get_Charmap_Index"); if(!dlFT_Get_Charmap_Index) return false; dlFT_Get_Char_Index = (FT_Get_Char_Index_t) libdyn.dlsym("FT_Get_Char_Index"); if(!dlFT_Get_Char_Index) return false; dlFT_Get_First_Char = (FT_Get_First_Char_t) libdyn.dlsym("FT_Get_First_Char"); if(!dlFT_Get_First_Char) return false; dlFT_Get_Next_Char = (FT_Get_Next_Char_t) libdyn.dlsym("FT_Get_Next_Char"); if(!dlFT_Get_Next_Char) return false; dlFT_Get_Name_Index = (FT_Get_Name_Index_t) libdyn.dlsym("FT_Get_Name_Index"); if(!dlFT_Get_Name_Index) return false; dlFT_Done_FreeType = (FT_Done_FreeType_t) libdyn.dlsym("FT_Done_FreeType"); if(!dlFT_Done_FreeType) return false; // generated-code:end return true; } return false; } #undef KLASS_VAR #define KLASS_VAR(Klass, Var) Klass Var static const SQChar Freetype_Tag[] = _SC("sqFreetype"); #define GET_freetype_INSTANCE_AT(idx, self) SQ_GET_INSTANCE2(v, idx, self, FT_Library, Freetype_Tag) \ if(self == NULL) return sq_throwerror(v, _SC("sqfreetype object already closed")); #define GET_freetype_INSTANCE() GET_freetype_INSTANCE_AT(1, self) static SQRESULT sq_freetype_releasehook(SQUserPointer p, SQInteger /*size*/, void */*ep*/) { FT_Library self = ((FT_Library)p); if(self) { dlFT_Done_FreeType(self); } return 1; } static SQRESULT sq_freetype_constructor(HSQUIRRELVM v) { if(!load_library(dynamicLibName)) return sq_throwerror(v, _SC("Failed to load libfreetype !")); FT_Library library; FT_Error error = dlFT_Init_FreeType( &library ); if(error) { return sq_throwerror(v,_SC("Failed to initialize FreeType library")); } sq_setinstanceup(v,1,library); sq_setreleasehook(v,1,sq_freetype_releasehook); return 0; } static SQRESULT sq_freetype_loadlib(HSQUIRRELVM v) { SQ_FUNC_VARS_NO_TOP(v); SQ_GET_STRING(v, 2, libname); sq_pushbool(v, load_library(libname)); return 1; } #define _DECL_FUNC(name,nparams,tycheck) {_SC(#name),sq_freetype_##name,nparams,tycheck} static SQRegFunction sq_freetype_methods[] = { _DECL_FUNC(constructor,1,_SC(".")), _DECL_FUNC(loadlib,2,_SC(".s")), {0,0} }; #undef _DECL_FUNC static const SQChar FreetypeFace_Tag[] = _SC("sqFreetypeFace"); #define GET_freetype_face_INSTANCE_AT(idx, self) SQ_GET_INSTANCE2(v, idx, self, FT_Face, FreetypeFace_Tag) \ if(self == NULL) return sq_throwerror(v, _SC("sqFreetypeFace object already closed")); #define GET_freetype_face_INSTANCE() GET_freetype_face_INSTANCE_AT(1, self) static SQRESULT sq_freetype_face_releasehook(SQUserPointer p, SQInteger /*size*/, void */*ep*/) { FT_Face self = ((FT_Face)p); if(self) { dlFT_Done_Face(self); } return 1; } static SQRESULT sq_freetype_face_constructor(HSQUIRRELVM v) { if(!load_library(dynamicLibName)) return sq_throwerror(v, _SC("Failed to load libpcre !")); SQ_FUNC_VARS(v); GET_freetype_INSTANCE_AT(2, library); SQ_GET_STRING(v, 3, fname); SQ_OPT_INTEGER(v, 4, face_index, 0); SQ_OPT_BOOL(v, 5, isMemory, SQFalse); FT_Face face; FT_Error error; if(isMemory) error = dlFT_New_Memory_Face(library, (const FT_Byte*)fname, fname_size, face_index, &face); else error = dlFT_New_Face(library, (const char*)fname, face_index, &face); if(error) { return sq_throwerror(v,_SC("Could not create freetype face")); } sq_setinstanceup(v,1,face); sq_setreleasehook(v,1,sq_freetype_face_releasehook); return 0; } static SQRESULT sq_freetype_face_set_char_size(HSQUIRRELVM v) { SQ_FUNC_VARS(v); GET_freetype_face_INSTANCE(); SQ_GET_INTEGER(v, 2, char_width); SQ_GET_INTEGER(v, 3, char_height); SQ_OPT_INTEGER(v, 4, horz_resolution, 0); SQ_OPT_INTEGER(v, 5, vert_resolution, 0); sq_pushinteger(v, dlFT_Set_Char_Size(self, char_width, char_height, horz_resolution, vert_resolution)); return 1; } static SQRESULT sq_freetype_face_load_char_or_glyph(HSQUIRRELVM v, bool onlyGlyph, bool asArray) { SQ_FUNC_VARS(v); GET_freetype_face_INSTANCE(); SQ_GET_INTEGER(v, 2, char_idx); SQ_OPT_INTEGER(v, 3, load_flags, FT_LOAD_RENDER); FT_GlyphSlot slot = self->glyph; FT_Error error; if(onlyGlyph) error = dlFT_Load_Char(self, char_idx, load_flags); else error = dlFT_Load_Char(self, char_idx, load_flags); if(error) sq_pushinteger(v, error); else { if(asArray) { sq_newarray(v, 8); sq_pushstring(v, (const SQChar*)slot->bitmap.buffer, slot->bitmap.width * slot->bitmap.rows * sizeof (unsigned char)); sq_arrayset(v, -2, 0); sq_pushinteger(v, slot->bitmap.width); sq_arrayset(v, -2, 1); sq_pushinteger(v, slot->bitmap.rows); sq_arrayset(v, -2, 2); sq_pushinteger(v, slot->metrics.horiBearingX); sq_arrayset(v, -2, 3); sq_pushinteger(v, slot->metrics.horiBearingY); sq_arrayset(v, -2, 4); sq_pushinteger(v, slot->metrics.horiAdvance); sq_arrayset(v, -2, 5); sq_pushinteger(v, slot->metrics.width); sq_arrayset(v, -2, 6); sq_pushinteger(v, slot->metrics.height); sq_arrayset(v, -2, 7); } else sq_pushstring(v, (const SQChar*)slot->bitmap.buffer, slot->bitmap.width * slot->bitmap.rows * sizeof (unsigned char)); } return 1; } static SQRESULT sq_freetype_face_load_char(HSQUIRRELVM v) { return sq_freetype_face_load_char_or_glyph(v, false, false); } static SQRESULT sq_freetype_face_load_char2(HSQUIRRELVM v) { return sq_freetype_face_load_char_or_glyph(v, false, true); } static SQRESULT sq_freetype_face_load_glyph(HSQUIRRELVM v) { return sq_freetype_face_load_char_or_glyph(v, true, false); } static SQRESULT sq_freetype_face_load_glyph2(HSQUIRRELVM v) { return sq_freetype_face_load_char_or_glyph(v, true, true); } static SQRESULT sq_freetype_face_char_index(HSQUIRRELVM v) { SQ_FUNC_VARS_NO_TOP(v); GET_freetype_face_INSTANCE(); SQ_GET_INTEGER(v, 2, glyph_idx); sq_pushinteger(v, dlFT_Get_Char_Index(self, glyph_idx)); return 1; } static SQRESULT sq_freetype_face_first_char(HSQUIRRELVM v) { SQ_FUNC_VARS_NO_TOP(v); GET_freetype_face_INSTANCE(); FT_UInt agindex; FT_ULong charcode = dlFT_Get_First_Char(self, &agindex); sq_newarray(v, 2); sq_pushinteger(v, charcode); sq_arrayset(v, -2, 0); sq_pushinteger(v, agindex); sq_arrayset(v, -2, 1); return 1; } static SQRESULT sq_freetype_face_next_char(HSQUIRRELVM v) { SQ_FUNC_VARS_NO_TOP(v); GET_freetype_face_INSTANCE(); SQ_GET_INTEGER(v, 2, char_idx); FT_UInt agindex; FT_ULong charcode = dlFT_Get_Next_Char(self, char_idx, &agindex); sq_newarray(v, 2); sq_pushinteger(v, charcode); sq_arrayset(v, -2, 0); sq_pushinteger(v, agindex); sq_arrayset(v, -2, 1); return 1; } static SQRESULT sq_freetype_face_name_index(HSQUIRRELVM v) { SQ_FUNC_VARS_NO_TOP(v); GET_freetype_face_INSTANCE(); SQ_GET_STRING(v, 2, char_name); FT_UInt gindex = dlFT_Get_Name_Index(self, (FT_String*)char_name); sq_pushinteger(v, gindex); return 1; } static SQRESULT sq_freetype_face_glyph_name(HSQUIRRELVM v) { SQ_FUNC_VARS_NO_TOP(v); GET_freetype_face_INSTANCE(); if(FT_HAS_GLYPH_NAMES(self)) { SQ_GET_INTEGER(v, 2, glyph_idx); SQInteger buf_size = 254; SQChar *buf = sq_getscratchpad(v, buf_size); FT_Error error = dlFT_Get_Glyph_Name(self, glyph_idx, buf, buf_size); if(error) sq_pushinteger(v, error); else sq_pushstring(v, buf, buf_size); } else sq_pushnull(v); return 1; } static SQRESULT sq_freetype_face_postscript_name(HSQUIRRELVM v) { SQ_FUNC_VARS_NO_TOP(v); GET_freetype_face_INSTANCE(); const char *pname = dlFT_Get_Postscript_Name(self); if(pname) sq_pushstring(v, pname, -1); else sq_pushnull(v); return 1; } static SQRESULT sq_freetype_face_get_num_glyphs(HSQUIRRELVM v) { SQ_FUNC_VARS_NO_TOP(v); GET_freetype_face_INSTANCE(); sq_pushinteger(v, self->num_glyphs); return 1; } static SQRESULT sq_freetype_face_metrics(HSQUIRRELVM v) { SQ_FUNC_VARS_NO_TOP(v); GET_freetype_face_INSTANCE(); sq_newtableex(v, 3); sq_pushliteral(v, _SC("ascender")); sq_pushinteger(v, self->ascender); sq_rawset(v, -3); sq_pushliteral(v, _SC("descender")); sq_pushinteger(v, self->descender); sq_rawset(v, -3); sq_pushliteral(v, _SC("height")); sq_pushinteger(v, self->height); sq_rawset(v, -3); return 1; } #define _DECL_FUNC(name,nparams,tycheck) {_SC(#name),sq_freetype_face_##name,nparams,tycheck} static SQRegFunction sq_freetype_face_methods[] = { _DECL_FUNC(constructor,-3,_SC(".xsnb")), _DECL_FUNC(set_char_size,-3,_SC(".iiii")), _DECL_FUNC(get_num_glyphs,1,_SC("x")), _DECL_FUNC(load_char,-2,_SC("xi")), _DECL_FUNC(load_char2,-2,_SC("xi")), _DECL_FUNC(load_glyph,-2,_SC("xi")), _DECL_FUNC(load_glyph2,-2,_SC("xi")), _DECL_FUNC(first_char,1,_SC("x")), _DECL_FUNC(next_char,2,_SC("xi")), _DECL_FUNC(char_index,2,_SC("xi")), _DECL_FUNC(name_index,2,_SC("xs")), _DECL_FUNC(glyph_name,2,_SC("xi")), _DECL_FUNC(postscript_name,1,_SC("x")), _DECL_FUNC(metrics,1,_SC("x")), {0,0} }; #undef _DECL_FUNC typedef struct { const SQChar *Str; SQInteger Val; } KeyIntType, * KeyIntPtrType; static KeyIntType sqfreetype_constants[] = { #define MK_CONST(c) {_SC(#c), c} #define MK_CONST2(c) {_SC(#c), (SQInteger)c} //MK_CONST(SSL_SESSION_ID_SIZE), MK_CONST(FT_LOAD_RENDER), MK_CONST(FT_LOAD_MONOCHROME), MK_CONST(FT_LOAD_TARGET_LIGHT), {0,0} }; #ifdef __cplusplus extern "C" { #endif SQRESULT sqext_register_freetype(HSQUIRRELVM v) { sq_pushstring(v, Freetype_Tag,-1); sq_newclass(v,SQFalse); sq_settypetag(v,-1,(void*)Freetype_Tag); sq_insert_reg_funcs(v, sq_freetype_methods); /* //add constants KeyIntPtrType KeyIntPtr; for (KeyIntPtr = sqfreetype_constants; KeyIntPtr->Str; KeyIntPtr++) { sq_pushstring(v, KeyIntPtr->Str, -1); //first the key sq_pushinteger(v, KeyIntPtr->Val); //then the value sq_newslot(v, -3, SQFalse); //store then } */ sq_newslot(v,-3,SQTrue); sq_pushstring(v, FreetypeFace_Tag,-1); sq_newclass(v,SQFalse); sq_settypetag(v,-1,(void*)FreetypeFace_Tag); sq_insert_reg_funcs(v, sq_freetype_face_methods); sq_newslot(v,-3,SQTrue); return 0; } #ifdef __cplusplus } #endif #endif // SQ_USE_FREETYPE