Created
November 7, 2025 01:20
-
-
Save fearofcode/0bd4bdf6e3b3f9bdc80f13293f2c27d2 to your computer and use it in GitHub Desktop.
simple console rendering proof of concept code for FreeType
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| cmake_minimum_required(VERSION 4.0) | |
| project(ute CXX C) | |
| set(CMAKE_CXX_STANDARD 17) | |
| find_program(CCACHE_FOUND ccache) | |
| if(CCACHE_FOUND) | |
| set_property(GLOBAL PROPERTY RULE_LAUNCH_COMPILE "${CCACHE_FOUND}") | |
| message(STATUS "Using ccache for compilation.") | |
| endif() | |
| include(FetchContent) | |
| FetchContent_Declare( | |
| freetype | |
| GIT_REPOSITORY https://gitlab.freedesktop.org/freetype/freetype.git | |
| GIT_TAG VER-2-14-1 | |
| ) | |
| set(FT_WITH_ZLIB OFF CACHE BOOL "Disable ZLIB support in FreeType") | |
| set(FT_WITH_BZIP2 OFF CACHE BOOL "Disable BZIP2 support in FreeType") | |
| set(FT_WITH_PNG OFF CACHE BOOL "Disable PNG support in FreeType") | |
| set(FT_WITH_HARFBUZZ OFF CACHE BOOL "Disable HarfBuzz support in FreeType") | |
| FetchContent_MakeAvailable(freetype) | |
| add_executable(ute main.cpp) | |
| # copy *.ttf files to cmake build dir so they will be available when running in an IDE | |
| file(GLOB FONT_FILES "${CMAKE_CURRENT_SOURCE_DIR}/*.ttf") | |
| add_custom_command( | |
| TARGET ute | |
| POST_BUILD | |
| COMMAND ${CMAKE_COMMAND} -E copy_if_different ${FONT_FILES} ${CMAKE_CURRENT_BINARY_DIR} | |
| ) | |
| target_link_libraries(ute PRIVATE freetype) |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #include <stdio.h> | |
| #include <string.h> | |
| #include <math.h> | |
| #include <ft2build.h> | |
| #include FT_FREETYPE_H | |
| #define WIDTH 128 | |
| #define HEIGHT 20 | |
| unsigned char image[HEIGHT][WIDTH]; | |
| void draw_bitmap(FT_Bitmap *bitmap, FT_Int x, FT_Int y) { | |
| FT_Int x_max = x + bitmap->width; | |
| FT_Int y_max = y + bitmap->rows; | |
| for (FT_Int i = x, p = 0; i < x_max; i++, p++) { | |
| for (FT_Int j = y, q = 0; j < y_max; j++, q++) { | |
| if (i < 0 || j < 0 || i >= WIDTH || j >= HEIGHT) | |
| continue; | |
| image[j][i] |= bitmap->buffer[q * bitmap->width + p]; | |
| } | |
| } | |
| } | |
| void show_image() { | |
| for (int i = 0; i < HEIGHT; i++) { | |
| for (int j = 0; j < WIDTH; j++) | |
| putchar(image[i][j] == 0 | |
| ? ' ' | |
| : image[i][j] < 128 | |
| ? '+' | |
| : '*'); | |
| putchar('\n'); | |
| } | |
| } | |
| int main(int argc, char **argv) { | |
| const char *filename = "Inconsolata-Regular.ttf"; | |
| const char *text = "Hello"; | |
| int target_height = 12; | |
| int num_chars = strlen(text); | |
| int font_size = 12; // pt | |
| FT_Library library; | |
| FT_Error error = FT_Init_FreeType(&library); | |
| FT_Face face; | |
| error = FT_New_Face(library, filename, 0, &face); | |
| error = FT_Set_Char_Size(face, font_size * 64, 0, 100, 0); | |
| FT_GlyphSlot slot = face->glyph; | |
| FT_Vector pen; | |
| pen.x = 0; | |
| pen.y = HEIGHT - 1; | |
| for (int n = 0; n < num_chars; n++) { | |
| FT_Set_Transform(face, nullptr, &pen); | |
| error = FT_Load_Char(face, text[n], FT_LOAD_RENDER); | |
| if (error) | |
| continue; | |
| draw_bitmap(&slot->bitmap, slot->bitmap_left, target_height - slot->bitmap_top); | |
| pen.x += slot->advance.x; | |
| pen.y += slot->advance.y; | |
| } | |
| show_image(); | |
| FT_Done_Face(face); | |
| FT_Done_FreeType(library); | |
| return 0; | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment