#include "text.h" #include #include #include "atlas.h" #include "freetype/freetype.h" #include "shaders.h" #include "utils.h" static void wayc_font_context_sampler_desc(struct sg_sampler_desc* desc) { wayc_notnull(desc); desc->min_filter = SG_FILTER_LINEAR; desc->mag_filter = SG_FILTER_LINEAR; desc->wrap_u = SG_WRAP_CLAMP_TO_EDGE; desc->wrap_v = SG_WRAP_CLAMP_TO_EDGE; } static void wayc_font_context_layout(struct sg_vertex_layout_state* layout) { wayc_notnull(layout); layout->buffers[0].stride = sizeof(text_vertex_s); layout->attrs[ATTR_text_in_position].format = SG_VERTEXFORMAT_FLOAT2; layout->attrs[ATTR_text_in_position].buffer_index = 0; layout->attrs[ATTR_text_in_position].offset = offsetof(text_vertex_s, pos); layout->attrs[ATTR_text_in_uv].format = SG_VERTEXFORMAT_FLOAT2; layout->attrs[ATTR_text_in_uv].buffer_index = 0; layout->attrs[ATTR_text_in_uv].offset = offsetof(text_vertex_s, uv); } static void wayc_font_context_color(struct sg_color_target_state* color) { wayc_notnull(color); struct sg_blend_state blend = {}; blend.enabled = true; blend.src_factor_rgb = SG_BLENDFACTOR_SRC_ALPHA; blend.dst_factor_rgb = SG_BLENDFACTOR_ONE_MINUS_SRC_ALPHA; blend.src_factor_alpha = SG_BLENDFACTOR_SRC_ALPHA; blend.dst_factor_alpha = SG_BLENDFACTOR_ONE_MINUS_SRC_ALPHA; color->blend = blend; } static void font_context_pipeline_desc(struct sg_pipeline_desc* desc, struct sg_shader shader) { wayc_notnull(desc); struct sg_vertex_layout_state vertex_layout = {}; wayc_font_context_layout(&vertex_layout); struct sg_color_target_state color = {}; wayc_font_context_color(&color); desc->layout = vertex_layout; desc->shader = shader; desc->colors[0] = color; desc->color_count = 1; } enum font_context_error_e wayc_font_context_init( struct font_context_s* context) { wayc_notnull(context); memset(context, 0, sizeof(*context)); bool success = false; FT_Library ft; FT_Error fterr = FT_Init_FreeType(&ft); if (fterr) return FONT_CONTEXT_ERROR_LOAD_LIBRARY; wayc_defer_cond(FT_Done_FreeType(ft), success, true); struct sg_shader shader = sg_make_shader(text_shader_desc(sg_query_backend())); if (sg_query_shader_state(shader) != SG_RESOURCESTATE_VALID) return FONT_CONTEXT_ERROR_CREATE_SHADER; wayc_defer_cond(sg_destroy_shader(shader), success, true); struct sg_sampler_desc sampler_desc = {}; wayc_font_context_sampler_desc(&sampler_desc); struct sg_pipeline_desc pipeline_desc = {}; font_context_pipeline_desc(&pipeline_desc, shader); struct sg_sampler sampler = sg_make_sampler(&sampler_desc); if (sg_query_sampler_state(sampler) != SG_RESOURCESTATE_VALID) return FONT_CONTEXT_ERROR_CREATE_SAMPLER; wayc_defer_cond(sg_destroy_sampler(sampler), success, true); struct sg_pipeline pipeline = sg_make_pipeline(&pipeline_desc); if (sg_query_pipeline_state(pipeline) != SG_RESOURCESTATE_VALID) return FONT_CONTEXT_ERROR_CREATE_PIPELINE; context->ft = ft; context->sampler = sampler; context->pipeline = pipeline; success = true; return FONT_CONTEXT_ERROR_NONE; } void wayc_font_context_deinit(struct font_context_s* context) { wayc_notnull(context); sg_destroy_pipeline(context->pipeline); sg_destroy_sampler(context->sampler); FT_Done_FreeType(context->ft); } enum font_error_e wayc_font_init(struct font_s* font, struct font_context_s* context, const char* path, u32 font_size, u32 atlas_width, u32 atlas_height) { wayc_notnull(font); wayc_notnull(context); memset(font, 0, sizeof(*font)); bool success = false; FT_Face face; FT_Error fterr = FT_New_Face(context->ft, path, 0, &face); if (fterr) return FONT_ERROR_LOAD_FACE; wayc_defer_cond(FT_Done_Face(face), success, true); struct atlas_s atlas; enum atlas_error_e aterr = wayc_atlas_init(&atlas, atlas_width, atlas_height, SG_PIXELFORMAT_R8); if (aterr) return FONT_ERROR_LOAD_FACE; font->face = face; font->font_size = font_size; font->atlas = atlas; success = true; return FONT_ERROR_NONE; } void wayc_font_deinit(struct font_s* font) { wayc_notnull(font); wayc_atlas_deinit(&font->atlas); FT_Done_Face(font->face); }