/* An expression in assert() can be expected to be executed absolutely. */ #undef NDEBUG #define SDL_MAIN_HANDLED #include #include #include #include #include #include "util/conv/charcode.h" #include "util/gleasy/buffer.h" #include "util/gleasy/program.h" #include "util/math/vector.h" #include "./cache.h" #include "./context.h" #include "./drawer.h" #include "./face.h" #include "./glyph.h" typedef struct { glyphas_context_t glyphas; glyphas_face_t face; gleasy_atlas_t* atlas; glyphas_cache_t* cache; gleasy_program_t prog; glyphas_drawer_t* drawer; } context_t; #define SCALE 0.01f static void align_text_(context_t* ctx, const char* str) { assert(ctx != NULL); const size_t len = strlen(str); glyphas_block_t* block = glyphas_block_new( GLYPHAS_ALIGNER_DIRECTION_HORIZONTAL, -20, 400, len); static vec4_t color = vec4(0, 0, 0, 1); glyphas_block_add_characters(block, ctx->cache, &color, str, len); vec2_t offset, size; glyphas_block_calculate_geometry(block, &offset, &size); offset = vec2(-offset.x, 0); glyphas_block_translate(block, &offset); size = vec2(1.f/200, 1.f/200); glyphas_block_scale(block, &size); static const vec2_t origin = vec2(.5f, -.5f); glyphas_block_set_origin(block, &origin); glyphas_drawer_clear(ctx->drawer, gleasy_atlas_get_texture(ctx->atlas), len); glyphas_drawer_add_block(ctx->drawer, block); glyphas_block_delete(block); } static void initialize_(context_t* ctx, const char* path, const char* str) { assert(ctx != NULL); *ctx = (typeof(*ctx)) {0}; glyphas_context_initialize(&ctx->glyphas); glyphas_face_initialize_from_file(&ctx->face, &ctx->glyphas, path, 0); ctx->atlas = gleasy_atlas_new(GL_RED, 256, 256, false /* anti-alias */); ctx->cache = glyphas_cache_new(ctx->atlas, &ctx->face, 16, 16); ctx->prog = glyphas_drawer_create_default_program(); ctx->drawer = glyphas_drawer_new(); assert(glGetError() == GL_NO_ERROR); align_text_(ctx, str); assert(glGetError() == GL_NO_ERROR); } static void draw_(const context_t* ctx) { assert(ctx != NULL); glEnable(GL_BLEND); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); glUseProgram(ctx->prog); glyphas_drawer_draw(ctx->drawer); } static void deinitialize_(context_t* ctx) { assert(ctx != NULL); glyphas_drawer_delete(ctx->drawer); glDeleteProgram(ctx->prog); glyphas_cache_delete(ctx->cache); gleasy_atlas_delete(ctx->atlas); glyphas_face_deinitialize(&ctx->face); glyphas_context_deinitialize(&ctx->glyphas); } typedef struct { SDL_Window* win; SDL_GLContext gl; } libs_t; static void initialize_libraries_(libs_t* libs) { assert(libs != NULL); SDL_SetHint(SDL_HINT_VIDEO_HIGHDPI_DISABLED, "0"); assert(SDL_Init(SDL_INIT_VIDEO) == 0); SDL_GL_SetAttribute( SDL_GL_CONTEXT_FLAGS, SDL_GL_CONTEXT_FORWARD_COMPATIBLE_FLAG); SDL_GL_SetAttribute( SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_CORE); SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 3); SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 3); SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1); static const uint32_t win_flags = SDL_WINDOW_ALLOW_HIGHDPI | SDL_WINDOW_OPENGL | SDL_WINDOW_SHOWN; libs->win = SDL_CreateWindow( "glyphas-test", /* title */ SDL_WINDOWPOS_CENTERED, /* X position */ SDL_WINDOWPOS_CENTERED, /* Y position */ 400, 400, win_flags); assert(libs->win != NULL); libs->gl = SDL_GL_CreateContext(libs->win); glewExperimental = 1; assert(glewInit() == GLEW_OK); } static void deinitialize_libraries_(libs_t* libs) { assert(libs != NULL); SDL_GL_DeleteContext(libs->gl); SDL_DestroyWindow(libs->win); SDL_Quit(); } int main(int argc, char** argv) { assert(argc == 3); libs_t libs; initialize_libraries_(&libs); context_t ctx; initialize_(&ctx, argv[1], argv[2]); bool alive = true; while (alive) { SDL_Delay(30); SDL_Event e; while (SDL_PollEvent(&e)) { if (e.type == SDL_QUIT) alive = false; } glClearColor(1, 1, 1, 1); glClear(GL_COLOR_BUFFER_BIT); draw_(&ctx); SDL_GL_SwapWindow(libs.win); } deinitialize_(&ctx); deinitialize_libraries_(&libs); return EXIT_SUCCESS; }