start work on font atlas creation
This commit is contained in:
parent
ead9c307bb
commit
2780f811f0
4
dub.json
4
dub.json
@ -11,11 +11,11 @@
|
||||
"sourceFiles-windows": [],
|
||||
"importPaths": ["src/gears", "src/codegen", "src/shared", "external/xxhash", "external/inteli"],
|
||||
"sourcePaths": ["src/gears", "src/codegen", "src/shared", "external/xxhash", "external/inteli"],
|
||||
"libs-linux": ["xcb", "X11", "X11-xcb", "vulkan", "stdc++", "xcb-xfixes"],
|
||||
"libs-linux": ["xcb", "X11", "X11-xcb", "vulkan", "stdc++", "xcb-xfixes", "freetype"],
|
||||
"libs-windows": [],
|
||||
"preGenerateCommands-linux": ["./build.sh", "build/Packer"],
|
||||
"preGenerateCommands-windows": [],
|
||||
"dflags": ["-Xcc=-mno-sse"],
|
||||
"dflags": ["-Xcc=-mno-sse", "-P-I/usr/include/freetype2"],
|
||||
"dflags-dmd": ["-P=-DSTBI_NO_SIMD"]
|
||||
},
|
||||
{
|
||||
|
||||
@ -116,7 +116,8 @@ InitGame(PlatformWindow* window)
|
||||
u8[] img_slice = img[0 .. width * height * 4];
|
||||
|
||||
CreateImageView(&g.rd, &g.font_tex, FONT_ATLAS.width, FONT_ATLAS.height, 4, img_slice);
|
||||
CreateImageView(&g.rd, &g.default_tex, 16, 16, 4, white_tex);
|
||||
// TODO: fix buffer overflow between two textures
|
||||
//CreateImageView(&g.rd, &g.default_tex, 16, 16, 4, white_tex);
|
||||
|
||||
WriteGUI(&g.rd, g.ui_desc_set, &g.font_tex);
|
||||
|
||||
@ -176,7 +177,7 @@ Cycle(Game* g)
|
||||
Reset(&g.frame_arena);
|
||||
|
||||
DrawRect(g, 500.0, 500.0, 800.0, 800.0, Vec4(0.2, 0.3, 0.7, 1.0));
|
||||
DrawText(g, 200.0, 200.0, 32.0, "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ");
|
||||
DrawText(g, 200.0, 200.0, FONT_ATLAS.size, "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ");
|
||||
|
||||
BeginFrame(&g.rd);
|
||||
|
||||
@ -330,13 +331,15 @@ DrawText(Game* g, f32 x, f32 y, f32 px, string str)
|
||||
{
|
||||
UIVertex* v = g.ui_vertex_buf.ptr + g.ui_count;
|
||||
|
||||
f32 w = px * (glyph.plane_right - glyph.plane_left);
|
||||
f32 r = px * glyph.plane_right;
|
||||
f32 l = px * glyph.plane_left;
|
||||
f32 w = r - l;
|
||||
f32 h = px * (glyph.plane_bottom - glyph.plane_top);
|
||||
f32 y_pos = px * glyph.plane_bottom;
|
||||
|
||||
v.dst_start.x = x_pos;
|
||||
v.dst_start.x = x_pos + l;
|
||||
v.dst_start.y = y + h - y_pos;
|
||||
v.dst_end.x = x_pos + w;
|
||||
v.dst_end.x = x_pos + w + l;
|
||||
v.dst_end.y = y - y_pos;
|
||||
|
||||
v.src_start.x = glyph.atlas_left;
|
||||
|
||||
@ -9,6 +9,10 @@ import core.simd;
|
||||
import math;
|
||||
import core.stdc.string : memcpy;
|
||||
|
||||
import font;
|
||||
import alloc;
|
||||
import assets;
|
||||
|
||||
// TODO:
|
||||
// 1. Determine how to better handle inputs
|
||||
// 2. Set up multisampling
|
||||
@ -19,6 +23,12 @@ void main(string[] argv)
|
||||
PlatformWindow window = CreateWindow("Video Game", 1920, 1080);
|
||||
Game g = InitGame(&window);
|
||||
|
||||
Arena arena = CreateArena(MB(8));
|
||||
InitFreeType();
|
||||
u8[] font_data = LoadAssetData(&arena, "fonts/NuberNextCondensed-DemiBold.otf");
|
||||
FontFace font = OpenFont(font_data);
|
||||
FontAtlasBuf atlas = CreateAtlas(&arena, font, 32.0, 256);
|
||||
|
||||
while (true)
|
||||
{
|
||||
HandleEvents(&window);
|
||||
|
||||
131
src/shared/font.d
Normal file
131
src/shared/font.d
Normal file
@ -0,0 +1,131 @@
|
||||
import aliases;
|
||||
import includes;
|
||||
import util;
|
||||
import alloc;
|
||||
|
||||
FT_Library FT_LIB;
|
||||
alias FontFace = FT_Face;
|
||||
|
||||
struct FontAtlasBuf
|
||||
{
|
||||
u8[] data;
|
||||
FontAtlas atlas;
|
||||
}
|
||||
|
||||
void
|
||||
InitFreeType()
|
||||
{
|
||||
FT_Init_FreeType(&FT_LIB);
|
||||
}
|
||||
|
||||
FontFace
|
||||
OpenFont(u8[] data)
|
||||
{
|
||||
FontFace font;
|
||||
FT_New_Memory_Face(FT_LIB, data.ptr, cast(FT_Long)data.length, 0, &font);
|
||||
return font;
|
||||
}
|
||||
|
||||
void
|
||||
CloseFont(FontFace font)
|
||||
{
|
||||
if (font != null)
|
||||
{
|
||||
FT_Done_Face(font);
|
||||
}
|
||||
}
|
||||
|
||||
FontAtlasBuf
|
||||
CreateAtlas(Arena* arena, FontFace font, f32 size, u64 dimension)
|
||||
{
|
||||
assert(dimension >= 128, "Dimension must be at least 128");
|
||||
|
||||
FontAtlasBuf atlas = {
|
||||
data: AllocArray!(u8)(arena, dimension * dimension * 4),
|
||||
};
|
||||
|
||||
// TODO: proper packing algorithm
|
||||
if (font != null)
|
||||
{
|
||||
FT_Set_Pixel_Sizes(font, 0, cast(FT_UInt)((96.0/72.0) * size));
|
||||
|
||||
i64 f_ascent = cast(i64)(font.size.metrics.ascender >> 6);
|
||||
i64 f_descent = cast(i64)(font.size.metrics.descender >> 6);
|
||||
i64 f_height = cast(i64)(font.size.metrics.height >> 6);
|
||||
|
||||
u32 max_w = 0;
|
||||
u32 max_h = 0;
|
||||
u32 current_h = 0;
|
||||
u32 count = 0;
|
||||
|
||||
FT_UInt index;
|
||||
FT_ULong char_code = FT_Get_First_Char(font, &index);
|
||||
while (index != 0)
|
||||
{
|
||||
FT_Load_Char(font, char_code, cast(FT_Int32)FT_LOAD_RENDER);
|
||||
|
||||
u32 bmp_w = font.glyph.bitmap.width;
|
||||
u32 bmp_h = font.glyph.bitmap.rows;
|
||||
if (max_w + bmp_w > dimension)
|
||||
{
|
||||
max_h += current_h;
|
||||
max_w = 0;
|
||||
}
|
||||
|
||||
assert(max_h < dimension, "Unable to pack atlas within dimensions");
|
||||
|
||||
max_w += bmp_w;
|
||||
current_h = bmp_h > current_h ? bmp_h : current_h;
|
||||
count += 1;
|
||||
|
||||
char_code = FT_Get_Next_Char(font, char_code, &index);
|
||||
}
|
||||
|
||||
atlas.atlas.glyphs = AllocArray!(Glyph)(arena, count);
|
||||
|
||||
max_w = 0;
|
||||
max_h = 0;
|
||||
current_h = 0;
|
||||
count = 0;
|
||||
|
||||
char_code = FT_Get_First_Char(font, &index);
|
||||
while (index != 0)
|
||||
{
|
||||
FT_Load_Char(font, char_code, cast(FT_Int32)FT_LOAD_RENDER);
|
||||
|
||||
FT_Bitmap* bmp = &font.glyph.bitmap;
|
||||
i32 top = font.glyph.bitmap_top;
|
||||
i32 left = font.glyph.bitmap_left;
|
||||
|
||||
if (max_w + bmp.rows > dimension)
|
||||
{
|
||||
max_h += current_h;
|
||||
max_w = 0;
|
||||
}
|
||||
|
||||
foreach(r; 0 .. bmp.rows)
|
||||
{
|
||||
i32 y = cast(i32)(max_h + r);
|
||||
foreach(c; 0 .. bmp.width)
|
||||
{
|
||||
i32 x = max_w + left + c;
|
||||
u64 offset = (y*dimension + x) * 4;
|
||||
|
||||
atlas.data[offset+0] = 255;
|
||||
atlas.data[offset+1] = 255;
|
||||
atlas.data[offset+2] = 255;
|
||||
atlas.data[offset+3] = bmp.buffer[r*bmp.pitch + c];
|
||||
}
|
||||
}
|
||||
|
||||
max_w += bmp.width;
|
||||
current_h = bmp.rows > current_h ? bmp.rows : current_h;
|
||||
|
||||
char_code = FT_Get_Next_Char(font, char_code, &index);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return atlas;
|
||||
}
|
||||
|
||||
@ -6,6 +6,9 @@
|
||||
# include <X11/Xlib.h>
|
||||
# include <X11/keysym.h>
|
||||
# include <X11/extensions/Xfixes.h>
|
||||
# include <ft2build.h>
|
||||
# include FT_FREETYPE_H
|
||||
# include FT_GLYPH_H
|
||||
#endif
|
||||
|
||||
#include <xmmintrin.h>
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user