123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518openCtypesopenForeignopenTsdlmoduleTtf=structtype'aresult='aSdl.result(* Set [debug] to true to print the foreign symbols in the CI. *)letdebug=Sys.getenv_opt"OCAMLCI"=Some"true"||Sys.getenv_opt"TSDL_DEBUG"=Some"true"letpre=ifdebugthenprint_endlineelseignoreleterror()=Error(`Msg(Sdl.get_error()))letzero_to_ok=letread=function0->Ok()|_err->error()inview~read~write:(fun_->assertfalse)intletbool=letread=function0->false|_->trueinletwrite=functiontrue->1|false->0inview~read~writeintletint32_as_uint32_t=view~read:Unsigned.UInt32.to_int32~write:Unsigned.UInt32.of_int32uint32_tletint64_as_long=view~read:Signed.Long.to_int64~write:Signed.Long.of_int64long(* let surface =
* view ~read:Sdl.unsafe_surface_of_ptr ~write:Sdl.unsafe_ptr_of_surface nativeint *)letsurface_result=letreadv=ifNativeint.(comparevzero)=0thenerror()elseOk(Sdl.unsafe_surface_of_ptrv)andwrite=function|Error_->raw_address_of_ptr@@null|Oks->Sdl.unsafe_ptr_of_surfacesinview~read~writenativeintletrw_ops=view~read:Sdl.unsafe_rw_ops_of_ptr~write:Sdl.unsafe_ptr_of_rw_opsnativeinttype_fonttypefont=_fontstructureptrletfont_struct:_fontstructuretyp=structure"TTF_Font"letfont:_fontstructureptrtyp=ptrfont_structletfont_opt:_fontstructureptroptiontyp=ptr_optfont_structletfont_result=letread=functionNone->error()|Somev->Okvandwrite=functionError_->None|Oks->Somesinview~read~writefont_opt(* pkg-config --variable=libdir SDL2_ttf *)(* Use Configurator.V1.Pkg_config instead? *)letpkg_config()=tryletic=Unix.open_process_in"pkg-config --variable=libdir SDL2_ttf"inletdir=input_lineicinclose_inic;Somedirwith_->None(* Dynamic loading at runtime solves two issues:
+ On linux if you want to use #require "tsdl-image"
in the toplevel, see
https://github.com/ocamllabs/ocaml-ctypes/issues/70
+ On Windows, linking with pkg-config flags raises the issue
of the wrong flags "-mwindows" "SDLMain", see
https://github.com/ocaml/flexdll/issues/163#issuecomment-3732220603
*)letperform_search():Dl.libraryoption=(ifdebugthenSdl.(log_infoLog.category_system"Loading Sdl_ttf, Target = %s"Build_config.system));letenv=trySys.getenv"LIBSDL2_PATH"withNot_found->""inletfilename,path=(* In principle only the basename is enough because the appropriate PATH
is used if SDL2_ttf was installed properly. We provide below more
hardcoded paths for non-standard installs where PATH is not correctly
set. *)match(Sys.os_type,Build_config.system)with|_,"macosx"->("libSDL2_ttf.dylib",["";"/opt/homebrew/lib/";"/opt/local/lib/";"/usr/local/lib/"])|"Win32",_|"Cygwin",_->("SDL2_ttf.dll",["";"/SDL2/SDL2_ttf/x86_64-w64-mingw32/bin";"/usr/x86_64-w64-mingw32/sys-root/mingw/bin";"/usr/i686-w64-mingw32/sys-root/mingw/bin";"/clangarm64/bin";"/clang64/bin";"/clang32/bin";"/ucrt64/bin";"/mingw64/bin";"/mingw32/bin";])|_->("libSDL2_ttf.so",["";"/usr/lib/x86_64-linux-gnu/";"/usr/local/lib"])inletrecloop=function|[]->None|dir::rest->(letfilename=ifdir=""thenfilenameelseFilename.concatdirfilenameintrySomeDl.(dlopen~filename~flags:[RTLD_NOW])with_->looprest)inmatchloop(env::path)with|Somef->Somef|None->((* We execute pkg_config only if everything else failed. *)matchpkg_config()with|Somedir->loop[dir]|None->print_endline("Cannot find "^filename^", please set LIBSDL2_PATH");None)letfrom:Dl.libraryoption=letshlib=trySys.getenv"LIBSDL2_TTF_SHLIB"withNot_found->""inifshlib=""thenperform_search()elseSomeDl.(dlopen~filename:shlib~flags:[RTLD_NOW])letforeign=foreign?fromletinit=pre"TTF_Init";foreign"TTF_Init"(void@->returningzero_to_ok)letversion=structure"SDL_version"letversion_major=fieldversion"major"uint8_tletversion_minor=fieldversion"minor"uint8_tletversion_patch=fieldversion"patch"uint8_tlet()=sealversionletlinked_version=pre"TTF_Linked_Version";foreign"TTF_Linked_Version"(void@->returning(ptrversion))letlinked_version()=letgetvf=Unsigned.UInt8.to_int(getfvf)inletv=linked_version()inletv=!@vin(getvversion_major,getvversion_minor,getvversion_patch)letversion=linked_version()let()=ifdebugthenleta,b,c=versioninSdl.log"SDL_ttf Version (%u,%u,%u)"abcletopen_font=pre"TTF_OpenFont";foreign"TTF_OpenFont"(string@->int@->returningfont_result)letopen_font_index=pre"TTF_OpenFontIndex";foreign"TTF_OpenFontIndex"(string@->int@->int64_as_long@->returningfont_result)letopen_font_rw=pre"TTF_OpenFontRW";foreign"TTF_OpenFontRW"(rw_ops@->int@->int@->returningfont_result)letopen_font_index_rw=pre"TTF_OpenFontIndexRW";foreign"TTF_OpenFontIndexRW"(rw_ops@->int@->int@->int64_as_long@->returningfont_result)(* let byte_swapped_unicode =
* pre "TTF_ByteSwappedUNICODE"; foreign "TTF_ByteSwappedUNICODE" (int @-> returning void) *)moduleStyle=structtypet=Unsigned.uint32leti=Unsigned.UInt32.of_intlet(+)=Unsigned.UInt32.logorlet(-)stflag=Unsigned.UInt32.(logandst(lognotflag))lettestfm=Unsigned.UInt32.(compare(logandfm)zero<>0)leteqff'=Unsigned.UInt32.(compareff'=0)letnormal=i0letbold=i1letitalic=i2letunderline=i4letstrikethrough=i8endletget_font_style=pre"TTF_GetFontStyle";foreign"TTF_GetFontStyle"(font@->returninguint32_t)letset_font_style=pre"TTF_SetFontStyle";foreign"TTF_SetFontStyle"(font@->uint32_t@->returningvoid)letget_font_outline=pre"TTF_GetFontOutline";foreign"TTF_GetFontOutline"(font@->returningint)letset_font_outline=pre"TTF_SetFontOutline";foreign"TTF_SetFontOutline"(font@->int@->returningvoid)moduleHinting=structtypet=Normal|Light|Mono|Nonelett=letread=function|0->Normal|1->Light|2->Mono|3->None|_->failwith"Unexpected value"inletwrite=functionNormal->0|Light->1|Mono->2|None->3inview~read~writeintendletget_font_hinting=pre"TTF_GetFontHinting";foreign"TTF_GetFontHinting"(font@->returningHinting.t)letset_font_hinting=pre"TTF_SetFontHinting";foreign"TTF_SetFontHinting"(font@->Hinting.t@->returningvoid)letfont_height=pre"TTF_FontHeight";foreign"TTF_FontHeight"(font@->returningint)letfont_ascent=pre"TTF_FontAscent";foreign"TTF_FontAscent"(font@->returningint)letfont_descent=pre"TTF_FontDescent";foreign"TTF_FontDescent"(font@->returningint)letfont_line_skip=pre"TTF_FontLineSkip";foreign"TTF_FontLineSkip"(font@->returningint)letget_font_kerning=pre"TTF_GetFontKerning";foreign"TTF_GetFontKerning"(font@->returningbool)letset_font_kerning=pre"TTF_SetFontKerning";foreign"TTF_SetFontKerning"(font@->bool@->returningvoid)letfont_faces=pre"TTF_FontFaces";foreign"TTF_FontFaces"(font@->returningint64_as_long)letfont_face_is_fixed_width=pre"TTF_FontFaceIsFixedWidth";foreign"TTF_FontFaceIsFixedWidth"(font@->returningint)letfont_face_family_name=pre"TTF_FontFaceFamilyName";foreign"TTF_FontFaceFamilyName"(font@->returningstring)letfont_face_style_name=pre"TTF_FontFaceStyleName";foreign"TTF_FontFaceStyleName"(font@->returningstring)letglyph_ucs2=view~read:Unsigned.UInt16.to_int~write:Unsigned.UInt16.of_intuint16_tletglyph_32=view~read:Unsigned.UInt32.to_int~write:Unsigned.UInt32.of_intuint32_tletglyph_is_provided=pre"TTF_GlyphIsProvided";foreign"TTF_GlyphIsProvided"(font@->glyph_ucs2@->returningbool)letglyph_is_provided32=pre"TTF_GlyphIsProvided32";ifversion>=(2,0,18)thenforeign"TTF_GlyphIsProvided32"(font@->glyph_32@->returningbool)elsefun_->failwith"TTF_GlyphIsProvided32 not implemented (need SDL_ttf >= 2.0.18)"moduleGlyphMetrics=structtypet={min_x:int;max_x:int;min_y:int;max_y:int;advance:int;}endletglyph_metrics=pre"TTF_GlyphMetrics";foreign"TTF_GlyphMetrics"(font@->glyph_ucs2@->ptrint@->ptrint@->ptrint@->ptrint@->ptrint@->returningint)letglyph_metrics32=pre"TTF_GlyphMetrics32";ifversion>=(2,0,18)thenforeign"TTF_GlyphMetrics32"(font@->glyph_32@->ptrint@->ptrint@->ptrint@->ptrint@->ptrint@->returningint)elsefun_->failwith"TTF_GlyphMetrics32 not implemented (need SDL_ttf >= 2.0.18)"letglyph_metrics_gmfg=letmin_x,max_x,min_y,max_y,advance=(allocateint0,allocateint0,allocateint0,allocateint0,allocateint0)inif0=gmfgmin_xmax_xmin_ymax_yadvancethenOkGlyphMetrics.{min_x=!@min_x;max_x=!@max_x;min_y=!@min_y;max_y=!@max_y;advance=!@advance;}elseerror()letglyph_metrics=glyph_metrics_glyph_metricsletglyph_metrics32=glyph_metrics_glyph_metrics32letsize_text=pre"TTF_SizeText";foreign"TTF_SizeText"(font@->string@->ptrint@->ptrint@->returningint)letsize_textfs=letw,h=(allocateint0,allocateint0)inif0=size_textfswhthenOk(!@w,!@h)elseerror()letsize_utf8=pre"TTF_SizeUTF8";foreign"TTF_SizeUTF8"(font@->string@->ptrint@->ptrint@->returningint)letsize_utf8fs=letw,h=(allocateint0,allocateint0)inif0=size_utf8fswhthenOk(!@w,!@h)elseerror()(* let size_unicode =
* pre "TTF_SizeUNICODE"; foreign "TTF_SizeUNICODE" (font @-> ptr glyph_ucs2 @-> ptr int @-> ptr int @-> returning int) *)type_colortypecolor=_colorstructureletcolor:colortyp=structure"SDL_Color"letcolor_r=fieldcolor"r"uint8_tletcolor_g=fieldcolor"g"uint8_tletcolor_b=fieldcolor"b"uint8_tletcolor_a=fieldcolor"a"uint8_tlet()=sealcolorletcolor=letreadv=letr,g,b,a=Unsigned.UInt8.(to_int@@getfvcolor_r,to_int@@getfvcolor_g,to_int@@getfvcolor_b,to_int@@getfvcolor_a)inSdl.Color.create~r~g~b~ainletwritev=letc=makecolorinsetfccolor_r(Unsigned.UInt8.of_int(Sdl.Color.rv));setfccolor_g(Unsigned.UInt8.of_int(Sdl.Color.gv));setfccolor_b(Unsigned.UInt8.of_int(Sdl.Color.bv));setfccolor_a(Unsigned.UInt8.of_int(Sdl.Color.av));cinview~read~writecolorletrender_text_solid=pre"TTF_RenderText_Solid";foreign"TTF_RenderText_Solid"(font@->string@->color@->returningsurface_result)letrender_utf8_solid=pre"TTF_RenderUTF8_Solid";foreign"TTF_RenderUTF8_Solid"(font@->string@->color@->returningsurface_result)(* let render_unicode_solid = pre "TTF_RenderUNICODE_Solid"; foreign "TTF_RenderUNICODE_Solid" (font @-> ptr glyph_ucs2 @-> color @-> returning surface_result) *)letrender_glyph_solid=pre"TTF_RenderGlyph_Solid";foreign"TTF_RenderGlyph_Solid"(font@->glyph_ucs2@->color@->returningsurface_result)letrender_glyph32_solid=pre"TTF_RenderGlyph32_Solid";ifversion>=(2,0,18)thenforeign"TTF_RenderGlyph32_Solid"(font@->glyph_32@->color@->returningsurface_result)elsefun_->failwith"TTF_RenderGlyph32_Solid not implemented (need SDL_ttf >= 2.0.18)"letrender_text_shaded=pre"TTF_RenderText_Shaded";foreign"TTF_RenderText_Shaded"(font@->string@->color@->color@->returningsurface_result)letrender_utf8_shaded=pre"TTF_RenderUTF8_Shaded";foreign"TTF_RenderUTF8_Shaded"(font@->string@->color@->color@->returningsurface_result)(* let render_unicode_shaded = pre "TTF_RenderUNICODE_Shaded"; foreign "TTF_RenderUNICODE_Shaded" (font @-> ptr glyph_ucs2 @-> color @-> color @-> returning surface_result) *)letrender_glyph_shaded=pre"TTF_RenderGlyph_Shaded";foreign"TTF_RenderGlyph_Shaded"(font@->glyph_ucs2@->color@->color@->returningsurface_result)letrender_glyph32_shaded=pre"TTF_RenderGlyph32_Shaded";ifversion>=(2,0,18)thenforeign"TTF_RenderGlyph32_Shaded"(font@->glyph_32@->color@->color@->returningsurface_result)elsefun_->failwith"TTF_RenderGlyph32_Shaded not implemented (need SDL_ttf >= 2.0.18)"letrender_text_blended=pre"TTF_RenderText_Blended";foreign"TTF_RenderText_Blended"(font@->string@->color@->returningsurface_result)letrender_utf8_blended=pre"TTF_RenderUTF8_Blended";foreign"TTF_RenderUTF8_Blended"(font@->string@->color@->returningsurface_result)(* let render_unicode_blended = pre "TTF_RenderUNICODE_Blended"; foreign "TTF_RenderUNICODE_Blended" (font @-> ptr glyph_ucs2 @-> color @-> returning surface_result) *)letrender_text_blended_wrapped=pre"TTF_RenderText_Blended_Wrapped";foreign"TTF_RenderText_Blended_Wrapped"(font@->string@->color@->int32_as_uint32_t@->returningsurface_result)letrender_utf8_blended_wrapped=pre"TTF_RenderUTF8_Blended_Wrapped";foreign"TTF_RenderUTF8_Blended_Wrapped"(font@->string@->color@->int32_as_uint32_t@->returningsurface_result)(* let render_unicode_blended_wrapped = pre "TTF_RenderUNICODE_Blended_Wrapped"; foreign "TTF_RenderUNICODE_Blended_Wrapped" (font @-> ptr glyph_ucs2 @-> color @-> int32_as_uint32_t @-> returning surface_result) *)letrender_glyph_blended=pre"TTF_RenderGlyph_Blended";foreign"TTF_RenderGlyph_Blended"(font@->glyph_ucs2@->color@->returningsurface_result)letrender_glyph32_blended=pre"TTF_RenderGlyph32_Blended";ifversion>=(2,0,18)thenforeign"TTF_RenderGlyph32_Blended"(font@->glyph_32@->color@->returningsurface_result)elsefun_->failwith"TTF_RenderGlyph32_Blended not implemented (need SDL_ttf >= 2.0.18)"letclose_font=pre"TTF_CloseFont";foreign"TTF_CloseFont"(font@->returningvoid)letquit=pre"TTF_Quit";foreign"TTF_Quit"(void@->returningvoid)letwas_init=pre"TTF_WasInit";foreign"TTF_WasInit"(void@->returningbool)letget_font_kerning_size=pre"TTF_GetFontKerningSize";foreign"TTF_GetFontKerningSize"(font@->int@->int@->returningint)end