#include "prx/libharfbuzz/include/FontFunctions.hpp" #include "prx/libc/include/General.hpp" #include #include #include static_assert(std::is_same_v); static_assert(std::is_same_v); static_assert(std::is_same_v); static_assert(sizeof(hb_glyph_extents_t) == 16 && alignof(hb_glyph_extents_t) == 4); namespace { struct FontData { void* data; HarfBuzz::Destroy destroy; }; template struct CallbackData { TCallback callback; void* data; HarfBuzz::Destroy destroy; }; void DestroyFontData(void* opaque) { const std::unique_ptr data(static_cast(opaque)); if (data->destroy) data->destroy(data->data); } template void DestroyCallbackData(void* opaque) { const std::unique_ptr> data(static_cast*>(opaque)); if (data->destroy) data->destroy(data->data); } void* UnwrapFontData(void* opaque) { return opaque ? static_cast(opaque)->data : nullptr; } template void SetCallback(hb_font_funcs_t* functions, TCallback callback, void* data, HarfBuzz::Destroy destroy, TNative adapter, TSetter setter) { if (!functions) NotImplemented_nid_no_patch(__func__); auto owner = std::make_unique>(callback, data, destroy); auto* payload = owner.release(); setter(functions, callback ? adapter : nullptr, payload, DestroyCallbackData); } int NominalGlyph(hb_font_t* font, void* fontData, std::uint32_t unicode, std::uint32_t* glyph, void* opaque) { const auto& data = *static_cast*>(opaque); return data.callback(font, UnwrapFontData(fontData), unicode, glyph, data.data); } int VariationGlyph(hb_font_t* font, void* fontData, std::uint32_t unicode, std::uint32_t selector, std::uint32_t* glyph, void* opaque) { const auto& data = *static_cast*>(opaque); return data.callback(font, UnwrapFontData(fontData), unicode, selector, glyph, data.data); } int GlyphExtents(hb_font_t* font, void* fontData, std::uint32_t glyph, hb_glyph_extents_t* extents, void* opaque) { const auto& data = *static_cast*>(opaque); return data.callback(font, UnwrapFontData(fontData), glyph, extents, data.data); } std::int32_t GlyphAdvance(hb_font_t* font, void* fontData, std::uint32_t glyph, void* opaque) { const auto& data = *static_cast*>(opaque); return data.callback(font, UnwrapFontData(fontData), glyph, data.data); } int GlyphOrigin(hb_font_t* font, void* fontData, std::uint32_t glyph, std::int32_t* x, std::int32_t* y, void* opaque) { const auto& data = *static_cast*>(opaque); return data.callback(font, UnwrapFontData(fontData), glyph, x, y, data.data); } } extern "C" { hb_font_t* APS5_VABI hb_font_create_nid_postfix(hb_face_t* face) { return hb_font_create(face); } void APS5_VABI hb_font_destroy_nid_postfix(hb_font_t* font) { hb_font_destroy(font); } hb_font_funcs_t* APS5_VABI hb_font_funcs_create_nid_postfix() { return hb_font_funcs_create(); } void APS5_VABI hb_font_funcs_make_immutable_nid_postfix(hb_font_funcs_t* functions) { if (!functions) NotImplemented_nid_no_patch(__func__); hb_font_funcs_make_immutable(functions); } void APS5_VABI hb_font_funcs_set_glyph_extents_func_nid_postfix(hb_font_funcs_t* functions, HarfBuzz::GlyphExtents callback, void* data, HarfBuzz::Destroy destroy) { SetCallback(functions, callback, data, destroy, GlyphExtents, hb_font_funcs_set_glyph_extents_func); } void APS5_VABI hb_font_funcs_set_glyph_func_nid_postfix(hb_font_funcs_t* functions, HarfBuzz::VariationGlyph callback, void* data, HarfBuzz::Destroy destroy) { if (!callback) NotImplemented_nid_no_patch(__func__); SetCallback(functions, callback, data, destroy, VariationGlyph, hb_font_funcs_set_glyph_func); } void APS5_VABI hb_font_funcs_set_glyph_h_advance_func_nid_postfix(hb_font_funcs_t* functions, HarfBuzz::GlyphAdvance callback, void* data, HarfBuzz::Destroy destroy) { SetCallback(functions, callback, data, destroy, GlyphAdvance, hb_font_funcs_set_glyph_h_advance_func); } void APS5_VABI hb_font_funcs_set_glyph_h_origin_func_nid_postfix(hb_font_funcs_t* functions, HarfBuzz::GlyphOrigin callback, void* data, HarfBuzz::Destroy destroy) { SetCallback(functions, callback, data, destroy, GlyphOrigin, hb_font_funcs_set_glyph_h_origin_func); } void APS5_VABI hb_font_funcs_set_nominal_glyph_func_nid_postfix(hb_font_funcs_t* functions, HarfBuzz::NominalGlyph callback, void* data, HarfBuzz::Destroy destroy) { SetCallback(functions, callback, data, destroy, NominalGlyph, hb_font_funcs_set_nominal_glyph_func); } void APS5_VABI hb_font_funcs_set_variation_glyph_func_nid_postfix(hb_font_funcs_t* functions, HarfBuzz::VariationGlyph callback, void* data, HarfBuzz::Destroy destroy) { SetCallback(functions, callback, data, destroy, VariationGlyph, hb_font_funcs_set_variation_glyph_func); } void APS5_VABI hb_font_make_immutable_nid_postfix(hb_font_t* font) { if (!font) NotImplemented_nid_no_patch(__func__); hb_font_make_immutable(font); } void APS5_VABI hb_font_set_funcs_nid_postfix(hb_font_t* font, hb_font_funcs_t* functions, void* data, HarfBuzz::Destroy destroy) { if (!font) NotImplemented_nid_no_patch(__func__); auto owner = std::make_unique(data, destroy); hb_font_set_funcs(font, functions, owner.release(), DestroyFontData); } void APS5_VABI hb_font_set_ppem_nid_postfix(hb_font_t* font, std::uint32_t x, std::uint32_t y) { if (!font) NotImplemented_nid_no_patch(__func__); hb_font_set_ppem(font, x, y); } void APS5_VABI hb_font_set_scale_nid_postfix(hb_font_t* font, std::int32_t x, std::int32_t y) { if (!font) NotImplemented_nid_no_patch(__func__); hb_font_set_scale(font, x, y); } }