| 277 | } |
| 278 | |
| 279 | UI_Font *UI_load_font_memory(UI_Context *ctx, unsigned char *data, size_t file_size, int ASCII_start, int ASCII_end, int *sizes, int sizes_count) |
| 280 | { |
| 281 | UI_assert(ctx != nullptr && "UI context *ctx is a null pointer!"); |
| 282 | UI_assert(ctx->initialized && "UI context wasn't initialized!"); |
| 283 | UI_assert(ctx->backend != UI_Render_Backend_Type::None && "No render backend is initialized!"); |
| 284 | |
| 285 | UI_Font newfont = {0}; |
| 286 | ctx->fonts.push_back(newfont); |
| 287 | UI_Font *font = &ctx->fonts.back(); |
| 288 | |
| 289 | FT_Face face; |
| 290 | FT_New_Memory_Face(ctx->ft_lib, data, file_size, 0, &face); |
| 291 | |
| 292 | int char_count = ASCII_end - ASCII_start + 1; |
| 293 | font->char_count = char_count; |
| 294 | |
| 295 | font->sizes = (int *)malloc(sizeof(int) * sizes_count); |
| 296 | font->true_sizes = (int *)malloc(sizeof(int) * sizes_count); |
| 297 | for (int i = 0; i < sizes_count; i++) { |
| 298 | font->sizes[i] = sizes[i]; |
| 299 | font->true_sizes[i] = 0; |
| 300 | } |
| 301 | |
| 302 | int w = 2000, h = 2000; // TODO(Wassim): fixed for now but we need a better way to handle this. |
| 303 | font->w = w; |
| 304 | font->h = h; |
| 305 | u8 *pixels_RGB = (u8 *)calloc(w * h * 3, sizeof(u8)); |
| 306 | u8 *pixels_RGBA = (u8 *)calloc(w * h * 4, sizeof(u8)); |
| 307 | int pen_x = 0, pen_y = 0; |
| 308 | font->char_info = (UI_Font_Glyph_Info *)malloc(sizeof(UI_Font_Glyph_Info) * char_count * sizes_count); |
| 309 | font->sizes_count = sizes_count; |
| 310 | int max_height_row = 0; |
| 311 | for (int size_index = 0; size_index < sizes_count; size_index++) { |
| 312 | int size_h = sizes[size_index] * 64 * 72 / 69.0f; |
| 313 | FT_Set_Char_Size(face, 0, size_h, 0, 0); |
| 314 | FT_BBox bbox = face->bbox; |
| 315 | for (int ASCII_code = ASCII_start; ASCII_code <= ASCII_end; ASCII_code++) { |
| 316 | FT_Load_Char(face, ASCII_code, FT_LOAD_RENDER | FT_LOAD_TARGET_LCD); |
| 317 | FT_GlyphSlot glyph_slot = face->glyph; |
| 318 | size_t offset = char_count * size_index; |
| 319 | UI_Font_Glyph_Info* target_char = &font->char_info[offset + ASCII_code - ASCII_start]; |
| 320 | FT_Bitmap* bitmap = &face->glyph->bitmap; |
| 321 | if(pen_x + bitmap->width >= w) { |
| 322 | pen_x = 0; |
| 323 | pen_y += max_height_row; |
| 324 | max_height_row = 0; |
| 325 | } |
| 326 | for(int row = 0; row < bitmap->rows; ++row){ |
| 327 | for(int col = 0; col < bitmap->width; col += 3){ |
| 328 | int x = pen_x + col / 3; |
| 329 | int y = pen_y + row; |
| 330 | pixels_RGB[y*w*3 + x*3 + 0] = bitmap->buffer[row * bitmap->pitch + col + 0]; |
| 331 | pixels_RGB[y*w*3 + x*3 + 1] = bitmap->buffer[row * bitmap->pitch + col + 1]; |
| 332 | pixels_RGB[y*w*3 + x*3 + 2] = bitmap->buffer[row * bitmap->pitch + col + 2]; |
| 333 | } |
| 334 | } |
| 335 | target_char->x0 = pen_x; |
| 336 | target_char->y0 = pen_y; |
no test coverage detected