fix freetype font loading
This commit is contained in:
parent
f211a29857
commit
69f5cd1a76
125
fonts.d
125
fonts.d
@ -88,6 +88,19 @@ CloseFont(FontFace font)
|
||||
}
|
||||
}
|
||||
|
||||
i32
|
||||
Float26(f32 f)
|
||||
{
|
||||
return cast(i32)round(cast(f32)(1 << 6) * f);
|
||||
}
|
||||
|
||||
u8
|
||||
DeMultiply(u8 color, u8 alpha)
|
||||
{
|
||||
u32 v = cast(u32)(255.0 * cast(f32)(color) / cast(f32)(alpha + f32.epsilon) + 0.5);
|
||||
return v > 255 ? 255 : cast(u8)v;
|
||||
}
|
||||
|
||||
FontAtlasBuf
|
||||
CreateAtlas(Arena* arena, FontFace font, f32 size, u32 dimension)
|
||||
{
|
||||
@ -105,8 +118,6 @@ CreateAtlas(Arena* arena, FontFace font, f32 size, u32 dimension)
|
||||
// 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);
|
||||
@ -116,8 +127,13 @@ CreateAtlas(Arena* arena, FontFace font, f32 size, u32 dimension)
|
||||
u32 current_h = 0;
|
||||
u32 count = 0;
|
||||
|
||||
i32 font_size = Float26(size);
|
||||
|
||||
FT_Library_SetLcdFilter(FT_LIB, FT_LCD_FILTER_NONE);
|
||||
|
||||
foreach(FT_ULong char_code; 0 .. 0x7F)
|
||||
{
|
||||
FT_Set_Char_Size(font, font_size, 0, 0, 0);
|
||||
FT_Error res = FT_Load_Char(font, char_code, cast(FT_Int32)FT_LOAD_RENDER);
|
||||
if (res != 0)
|
||||
{
|
||||
@ -139,16 +155,16 @@ CreateAtlas(Arena* arena, FontFace font, f32 size, u32 dimension)
|
||||
count += 1;
|
||||
}
|
||||
|
||||
max_w = 0;
|
||||
max_h = 0;
|
||||
const u32 PADDING = 2;
|
||||
|
||||
max_w = PADDING;
|
||||
max_h = PADDING;
|
||||
current_h = 0;
|
||||
count = 0;
|
||||
|
||||
u32 font_w = font.size.metrics.x_ppem;
|
||||
u32 font_h = font.size.metrics.y_ppem;
|
||||
|
||||
foreach(FT_ULong char_code; 0 .. 0x7F)
|
||||
{
|
||||
FT_Set_Char_Size(font, font_size, 0, 0, 0);
|
||||
FT_Error res = FT_Load_Char(font, char_code, cast(FT_Int32)FT_LOAD_RENDER);
|
||||
if (res != 0)
|
||||
{
|
||||
@ -162,24 +178,88 @@ CreateAtlas(Arena* arena, FontFace font, f32 size, u32 dimension)
|
||||
|
||||
if (max_w + bmp.rows > dimension)
|
||||
{
|
||||
max_h += current_h;
|
||||
max_w = 0;
|
||||
max_h += cast(u32)(size) + PADDING;
|
||||
max_w = PADDING;
|
||||
}
|
||||
|
||||
i32 x, y;
|
||||
foreach(r; 0 .. bmp.rows)
|
||||
switch(bmp.pixel_mode)
|
||||
{
|
||||
y = cast(i32)(max_h + r);
|
||||
foreach(c; 0 .. bmp.width)
|
||||
{
|
||||
x = max_w + c;
|
||||
u64 offset = (y*dimension + x) * 4;
|
||||
case FT_PIXEL_MODE_BGRA:
|
||||
{
|
||||
i32 x, y;
|
||||
foreach(r; 0 .. bmp.rows)
|
||||
{
|
||||
y = cast(i32)(max_h + r);
|
||||
foreach(c; 0 .. bmp.width)
|
||||
{
|
||||
x = max_w + 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];
|
||||
}
|
||||
u8 p_b = bmp.buffer[offset+0];
|
||||
u8 p_g = bmp.buffer[offset+1];
|
||||
u8 p_r = bmp.buffer[offset+2];
|
||||
u8 p_a = bmp.buffer[offset+3];
|
||||
|
||||
atlas.data[offset+0] = DeMultiply(p_r, p_a);
|
||||
atlas.data[offset+1] = DeMultiply(p_b, p_a);
|
||||
atlas.data[offset+2] = DeMultiply(p_g, p_a);
|
||||
atlas.data[offset+3] = p_a;
|
||||
}
|
||||
}
|
||||
} break;
|
||||
case FT_PIXEL_MODE_MONO:
|
||||
{
|
||||
u32 pitch = bmp.pitch;
|
||||
u8* buf = bmp.buffer;
|
||||
i32 x, y;
|
||||
foreach(r; 0 .. bmp.rows)
|
||||
{
|
||||
u8 bits = 0;
|
||||
u8* buf_ptr = buf;
|
||||
y = cast(i32)(max_h + r);
|
||||
foreach(c; 0 .. bmp.width)
|
||||
{
|
||||
if ((c & 7) == 0)
|
||||
{
|
||||
bits = *buf_ptr;
|
||||
buf_ptr += 1;
|
||||
}
|
||||
|
||||
x = max_w + 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] = (bits & 0x80) ? 255 : 0;
|
||||
|
||||
bits <<= 1;
|
||||
}
|
||||
|
||||
buf += pitch;
|
||||
}
|
||||
} break;
|
||||
case FT_PIXEL_MODE_GRAY:
|
||||
{
|
||||
i32 x, y;
|
||||
foreach(r; 0 .. bmp.rows)
|
||||
{
|
||||
y = cast(i32)(max_h + r);
|
||||
foreach(c; 0 .. bmp.width)
|
||||
{
|
||||
x = max_w + 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];
|
||||
}
|
||||
}
|
||||
} break;
|
||||
default:
|
||||
assert(false, "Unknown pixel_mode value");
|
||||
break;
|
||||
}
|
||||
|
||||
Glyph* g = atlas.atlas.glyphs.ptr + char_code;
|
||||
@ -196,7 +276,7 @@ CreateAtlas(Arena* arena, FontFace font, f32 size, u32 dimension)
|
||||
g.atlas_bottom = max_h + bmp.rows;
|
||||
g.atlas_right = max_w + bmp.width;
|
||||
|
||||
max_w += bmp.width;
|
||||
max_w += bmp.width + PADDING;
|
||||
current_h = bmp.rows > current_h ? bmp.rows : current_h;
|
||||
|
||||
count += 1;
|
||||
@ -206,3 +286,4 @@ CreateAtlas(Arena* arena, FontFace font, f32 size, u32 dimension)
|
||||
return atlas;
|
||||
}
|
||||
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user