Extract font grid from raylib
This commit is contained in:
@@ -61,7 +61,7 @@ Rect2 GetScreenRectRenderUnits() {
|
|||||||
|
|
||||||
// Draw text using Font
|
// Draw text using Font
|
||||||
// NOTE: chars spacing is NOT proportional to fontSize
|
// NOTE: chars spacing is NOT proportional to fontSize
|
||||||
void DrawTextNew(Font font, String text, Vector2 position, float fontSize, float spacing, Color tint) {
|
void DrawString(Font font, String text, Vector2 position, float fontSize, float spacing, Color tint) {
|
||||||
if (font.texture.id == 0) font = GetFontDefault(); // Security check in case of not valid font
|
if (font.texture.id == 0) font = GetFontDefault(); // Security check in case of not valid font
|
||||||
|
|
||||||
float textOffsetX = 0.0f; // Offset X to next character to draw
|
float textOffsetX = 0.0f; // Offset X to next character to draw
|
||||||
@@ -93,32 +93,34 @@ int main() {
|
|||||||
SetTargetFPS(60);
|
SetTargetFPS(60);
|
||||||
|
|
||||||
InitArena(&FrameArena);
|
InitArena(&FrameArena);
|
||||||
float font_size = 14;
|
float font_size = 25;
|
||||||
float font_spacing = 1;
|
float font_spacing = 1;
|
||||||
Font font = LoadFontEx("C:/Windows/Fonts/consola.ttf", (int)font_size, NULL, 250);
|
Font font = LoadFontEx("C:/Windows/Fonts/times.ttf", (int)font_size, NULL, 250);
|
||||||
|
|
||||||
Buffer buffer = {};
|
|
||||||
InitBuffer(&buffer);
|
|
||||||
for (int i = 0; i < 100; i += 1) {
|
|
||||||
Array<Edit> edits = {FrameArena};
|
|
||||||
AddEdit(&edits, GetEnd(buffer), Format(FrameArena, "line number: %d\n", i));
|
|
||||||
ApplyEdits(&buffer, edits);
|
|
||||||
}
|
|
||||||
|
|
||||||
Array<Window> windows = {};
|
Array<Window> windows = {};
|
||||||
windows.add({GetScreenRectRenderUnits()});
|
windows.add({GetScreenRectRenderUnits()});
|
||||||
|
{
|
||||||
|
Buffer *buffer = &windows[0].buffer;
|
||||||
|
InitBuffer(buffer);
|
||||||
|
for (int i = 0; i < 100; i += 1) {
|
||||||
|
Array<Edit> edits = {FrameArena};
|
||||||
|
AddEdit(&edits, GetEnd(*buffer), Format(FrameArena, "line number: %d\n", i));
|
||||||
|
ApplyEdits(buffer, edits);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Vec2 camera_offset_world_to_render_units = {};
|
Vec2 camera_offset_world_to_render_units = {};
|
||||||
while (!WindowShouldClose()) {
|
while (!WindowShouldClose()) {
|
||||||
|
{
|
||||||
|
Window *focused_window = &windows[0];
|
||||||
|
|
||||||
if (IsMouseButtonDown(MOUSE_BUTTON_LEFT) || IsKeyDown(KEY_SPACE)) {
|
if (IsMouseButtonDown(MOUSE_BUTTON_LEFT) || IsKeyDown(KEY_SPACE)) {
|
||||||
camera_offset_world_to_render_units = Vector2Subtract(camera_offset_world_to_render_units, GetMouseDelta());
|
camera_offset_world_to_render_units = Vector2Subtract(camera_offset_world_to_render_units, GetMouseDelta());
|
||||||
}
|
}
|
||||||
{
|
|
||||||
Window *focused_window = &windows[0];
|
|
||||||
float mouse_wheel = GetMouseWheelMove() * 48;
|
float mouse_wheel = GetMouseWheelMove() * 48;
|
||||||
focused_window->window_world_to_window_units.y -= mouse_wheel;
|
focused_window->window_world_to_window_units.y -= mouse_wheel;
|
||||||
focused_window->window_world_to_window_units.y = ClampBottom(focused_window->window_world_to_window_units.y, 0.f);
|
focused_window->window_world_to_window_units.y = ClampBottom(focused_window->window_world_to_window_units.y, 0.f);
|
||||||
}
|
|
||||||
|
|
||||||
for (int c = GetCharPressed(); c; c = GetCharPressed()) {
|
for (int c = GetCharPressed(); c; c = GetCharPressed()) {
|
||||||
String string = "?";
|
String string = "?";
|
||||||
@@ -129,7 +131,8 @@ int main() {
|
|||||||
|
|
||||||
Array<Edit> edits = {FrameArena};
|
Array<Edit> edits = {FrameArena};
|
||||||
AddEdit(&edits, {}, string);
|
AddEdit(&edits, {}, string);
|
||||||
ApplyEdits(&buffer, edits);
|
ApplyEdits(&focused_window->buffer, edits);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
BeginDrawing();
|
BeginDrawing();
|
||||||
@@ -143,27 +146,11 @@ int main() {
|
|||||||
Rectangle rectangle_in_render_units = ToRectangle(window_rect_in_render_units);
|
Rectangle rectangle_in_render_units = ToRectangle(window_rect_in_render_units);
|
||||||
DrawRectangleRec(rectangle_in_render_units, WHITE);
|
DrawRectangleRec(rectangle_in_render_units, WHITE);
|
||||||
|
|
||||||
// @todo: add window bar?
|
|
||||||
// {
|
|
||||||
// Vec2 text_position_in_window_units = {};
|
|
||||||
// Vec2 text_position_in_world_units = WindowToWorldUnits(text_position_in_window_units, it);
|
|
||||||
// Vec2 text_position_in_render_units = WorldToRenderUnits(text_position_in_world_units, camera_offset_world_to_render_units);
|
|
||||||
// DrawTextEx(font, "window 1", text_position_in_render_units, font_size, font_spacing, BLACK);
|
|
||||||
// }
|
|
||||||
|
|
||||||
//
|
//
|
||||||
// Line rendering
|
// Line rendering
|
||||||
//
|
//
|
||||||
{
|
// @todo: how to constrain x?
|
||||||
// @todo: how do I implement the minimal drawing of text
|
// @optimize: I could clip to visible on screen window_rectangle but I couldn't get it right
|
||||||
// Rect2 screen_rect_in_render_units = GetScreenRectRenderUnits();
|
|
||||||
// Rect2 window_rect_in_render_units_clamped_to_screen = window_rect_in_render_units;
|
|
||||||
// window_rect_in_render_units_clamped_to_screen.min.x = Clamp(window_rect_in_render_units_clamped_to_screen.min.x, screen_rect_in_render_units.min.x, screen_rect_in_render_units.max.x);
|
|
||||||
// window_rect_in_render_units_clamped_to_screen.max.x = Clamp(window_rect_in_render_units_clamped_to_screen.max.x, screen_rect_in_render_units.min.x, screen_rect_in_render_units.max.x);
|
|
||||||
// window_rect_in_render_units_clamped_to_screen.min.y = Clamp(window_rect_in_render_units_clamped_to_screen.min.y, screen_rect_in_render_units.min.y, screen_rect_in_render_units.max.y);
|
|
||||||
// window_rect_in_render_units_clamped_to_screen.max.y = Clamp(window_rect_in_render_units_clamped_to_screen.max.y, screen_rect_in_render_units.min.y, screen_rect_in_render_units.max.y);
|
|
||||||
|
|
||||||
// @todo: x
|
|
||||||
Vec2 s = GetSize(window_rect_in_render_units);
|
Vec2 s = GetSize(window_rect_in_render_units);
|
||||||
float line_offset = font_size;
|
float line_offset = font_size;
|
||||||
float _line_min_y = (window.window_world_to_window_units.y) / line_offset;
|
float _line_min_y = (window.window_world_to_window_units.y) / line_offset;
|
||||||
@@ -175,21 +162,46 @@ int main() {
|
|||||||
BeginScissorMode((int)window_rect_in_render_units.min.x, (int)window_rect_in_render_units.min.y, (int)window_rect_in_render_units_size.x, (int)window_rect_in_render_units_size.y);
|
BeginScissorMode((int)window_rect_in_render_units.min.x, (int)window_rect_in_render_units.min.y, (int)window_rect_in_render_units_size.x, (int)window_rect_in_render_units_size.y);
|
||||||
for (int64_t line = line_min_y; line < line_max_y; line += 1) {
|
for (int64_t line = line_min_y; line < line_max_y; line += 1) {
|
||||||
if (line < 0) break;
|
if (line < 0) break;
|
||||||
if (line >= buffer.lines.len) break;
|
if (line >= window.buffer.lines.len) break;
|
||||||
|
|
||||||
Range line_range = buffer.lines[line];
|
Range line_range = window.buffer.lines[line];
|
||||||
|
|
||||||
Vec2 text_position_in_world_window_units = {0, line_offset * (float)line};
|
Vec2 text_position_in_world_window_units = {0, line_offset * (float)line};
|
||||||
Vec2 text_position_in_window_units = WindowWorldToWindowUnits(text_position_in_world_window_units, window);
|
Vec2 text_position_in_window_units = WindowWorldToWindowUnits(text_position_in_world_window_units, window);
|
||||||
Vec2 text_position_in_world_units = WindowToWorldUnits(text_position_in_window_units, window);
|
Vec2 text_position_in_world_units = WindowToWorldUnits(text_position_in_window_units, window);
|
||||||
Vec2 text_position_in_render_units = WorldToRenderUnits(text_position_in_world_units, camera_offset_world_to_render_units);
|
Vec2 text_position_in_render_units = WorldToRenderUnits(text_position_in_world_units, camera_offset_world_to_render_units);
|
||||||
|
|
||||||
String string = GetString(buffer, line_range);
|
//
|
||||||
DrawTextNew(font, string, text_position_in_render_units, font_size, font_spacing, BLACK);
|
// Glyph inside the line rendering
|
||||||
|
//
|
||||||
|
String text = GetString(window.buffer, line_range);
|
||||||
|
if (font.texture.id == 0) font = GetFontDefault();
|
||||||
|
float textOffsetX = 0.0f;
|
||||||
|
float scaleFactor = font_size / font.baseSize; // Character quad scaling factor
|
||||||
|
for (int i = 0; i < text.len;) {
|
||||||
|
int codepointByteCount = 0;
|
||||||
|
int codepoint = GetCodepointNext(&text.data[i], &codepointByteCount);
|
||||||
|
int index = GetGlyphIndex(font, codepoint);
|
||||||
|
GlyphInfo *glyph = font.glyphs + index;
|
||||||
|
Vec2 glyph_position = {text_position_in_render_units.x + textOffsetX, text_position_in_render_units.y};
|
||||||
|
|
||||||
|
float x_to_offset_by = ((float)glyph->advanceX * scaleFactor + font_spacing);
|
||||||
|
if (glyph->advanceX == 0) x_to_offset_by = ((float)font.recs[index].width * scaleFactor + font_spacing);
|
||||||
|
|
||||||
|
Vec2 cell_size = {x_to_offset_by, font_size};
|
||||||
|
Rect2 cell_rect = {glyph_position, Vector2Add(glyph_position, cell_size)};
|
||||||
|
|
||||||
|
DrawRectangleLinesEx(ToRectangle(cell_rect), 1, {255, 0, 0, 120});
|
||||||
|
if ((codepoint != ' ') && (codepoint != '\t')) {
|
||||||
|
DrawTextCodepoint(font, codepoint, glyph_position, font_size, BLACK);
|
||||||
|
}
|
||||||
|
|
||||||
|
textOffsetX += x_to_offset_by;
|
||||||
|
i += codepointByteCount; // Move text bytes counter to next codepoint
|
||||||
|
}
|
||||||
}
|
}
|
||||||
EndScissorMode();
|
EndScissorMode();
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
EndDrawing();
|
EndDrawing();
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user