smth
This commit is contained in:
parent
8f4f5e4ca4
commit
f93505cd26
@ -39,6 +39,8 @@ set(HB_HAVE_FREETYPE ON CACHE BOOL "" FORCE)
|
|||||||
set(HB_HAVE_GLIB OFF CACHE BOOL "" FORCE)
|
set(HB_HAVE_GLIB OFF CACHE BOOL "" FORCE)
|
||||||
set(HB_HAVE_ICU OFF CACHE BOOL "" FORCE)
|
set(HB_HAVE_ICU OFF CACHE BOOL "" FORCE)
|
||||||
|
|
||||||
|
FetchContent_MakeAvailable(harfbuzz)
|
||||||
|
|
||||||
FetchContent_Declare(
|
FetchContent_Declare(
|
||||||
stb
|
stb
|
||||||
GIT_REPOSITORY https://github.com/nothings/stb.git
|
GIT_REPOSITORY https://github.com/nothings/stb.git
|
||||||
@ -58,7 +60,8 @@ endif()
|
|||||||
FetchContent_Declare(
|
FetchContent_Declare(
|
||||||
tracy
|
tracy
|
||||||
GIT_REPOSITORY https://github.com/wolfpld/tracy.git
|
GIT_REPOSITORY https://github.com/wolfpld/tracy.git
|
||||||
GIT_TAG 05cceee0df3b8d7c6fa87e9638af311dbabc63cb
|
GIT_TAG master
|
||||||
|
SYSTEM
|
||||||
)
|
)
|
||||||
|
|
||||||
FetchContent_MakeAvailable(tracy)
|
FetchContent_MakeAvailable(tracy)
|
||||||
|
|||||||
487
src/font.cpp
487
src/font.cpp
@ -10,6 +10,9 @@
|
|||||||
#include <stb_rect_pack.h>
|
#include <stb_rect_pack.h>
|
||||||
#include <tracy/Tracy.hpp>
|
#include <tracy/Tracy.hpp>
|
||||||
|
|
||||||
|
#include "raymath.h"
|
||||||
|
#include "tracy/TracyC.h"
|
||||||
|
|
||||||
FT_Library ft_lib;
|
FT_Library ft_lib;
|
||||||
Shader shader;
|
Shader shader;
|
||||||
|
|
||||||
@ -22,11 +25,14 @@ MyFont::MyFont(const std::string& filename, int size) {
|
|||||||
if (!file.is_open()) throw std::runtime_error("Failed to open font file");
|
if (!file.is_open()) throw std::runtime_error("Failed to open font file");
|
||||||
|
|
||||||
std::streamsize file_size = file.tellg();
|
std::streamsize file_size = file.tellg();
|
||||||
font_data.resize(file_size);
|
std::vector<uint8_t> file_data(file_size);
|
||||||
file.seekg(0, std::ios::beg);
|
file.seekg(0, std::ios::beg);
|
||||||
file.read(reinterpret_cast<char*>(font_data.data()), file_size);
|
file.read(reinterpret_cast<char*>(file_data.data()), file_size);
|
||||||
|
|
||||||
if (FT_New_Memory_Face(ft_lib, font_data.data(), font_data.size(), 0, &face)) {
|
kb_file_data = file_data;
|
||||||
|
|
||||||
|
face = {};
|
||||||
|
if (FT_New_Memory_Face(ft_lib, file_data.data(), file_data.size(), 0, &face)) {
|
||||||
throw std::runtime_error("Failed to create FreeType face");
|
throw std::runtime_error("Failed to create FreeType face");
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -34,7 +40,6 @@ MyFont::MyFont(const std::string& filename, int size) {
|
|||||||
FT_Set_Char_Size(face, 0, size * 64, 0, (FT_UInt)(96 * dpi.y));
|
FT_Set_Char_Size(face, 0, size * 64, 0, (FT_UInt)(96 * dpi.y));
|
||||||
FT_Select_Charmap(face, FT_ENCODING_UNICODE);
|
FT_Select_Charmap(face, FT_ENCODING_UNICODE);
|
||||||
|
|
||||||
// Rect packing setup
|
|
||||||
std::vector<stbrp_rect> rects;
|
std::vector<stbrp_rect> rects;
|
||||||
rects.reserve(face->num_glyphs);
|
rects.reserve(face->num_glyphs);
|
||||||
|
|
||||||
@ -98,6 +103,12 @@ MyFont::MyFont(const std::string& filename, int size) {
|
|||||||
glyphs[g.index] = g;
|
glyphs[g.index] = g;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
kbts = kbts_FontFromMemory(kb_file_data.data(), kb_file_data.size(), 0, nullptr, nullptr);
|
||||||
|
|
||||||
|
if (kbts_FontIsValid(&kbts) == 0) {
|
||||||
|
std::println("[Error] [kb_text_shape] Failed to load the font.");
|
||||||
|
}
|
||||||
|
|
||||||
Image img = {
|
Image img = {
|
||||||
.data = atlas_data.data(),
|
.data = atlas_data.data(),
|
||||||
.width = ATLAS_SIZE,
|
.width = ATLAS_SIZE,
|
||||||
@ -110,26 +121,42 @@ MyFont::MyFont(const std::string& filename, int size) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void MyFont::deinit() {
|
void MyFont::deinit() {
|
||||||
|
kbts_FreeFont(&kbts);
|
||||||
if (face) FT_Done_Face(face);
|
if (face) FT_Done_Face(face);
|
||||||
UnloadTexture(texture);
|
UnloadTexture(texture);
|
||||||
glyphs.clear();
|
glyphs.clear();
|
||||||
font_data.clear();
|
kb_file_data.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
void MyFont::render_text(const std::string_view text, const Vector2 pos, const Color color) {
|
void MyFont::render_text(const std::string_view text, const Vector2 pos, const Color colour)
|
||||||
if (text.size() == 0)
|
{
|
||||||
|
if (text.empty())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
// if (nice_background) {
|
||||||
|
// self.render_text(
|
||||||
|
// text,
|
||||||
|
// pos.add(.{.x = 3.0, .y = -3.0}),
|
||||||
|
// window_space,
|
||||||
|
// rl.Color{ .r = 0, .g = 0, .b = 0, .a = 255 },
|
||||||
|
// rl.Color{ .r = 0, .g = 0, .b = 0, .a = 0 },
|
||||||
|
// false,
|
||||||
|
// false
|
||||||
|
// );
|
||||||
|
// }
|
||||||
|
|
||||||
ZoneScoped
|
ZoneScoped
|
||||||
|
|
||||||
|
Vector2 render_pos = pos;
|
||||||
|
|
||||||
BeginShaderMode(shader);
|
BeginShaderMode(shader);
|
||||||
rlSetTexture(texture.id);
|
rlSetTexture(texture.id);
|
||||||
rlBegin(RL_QUADS);
|
rlBegin(RL_QUADS);
|
||||||
|
|
||||||
Vector2 dpi = GetWindowScaleDPI();
|
const float font_ascent = face->size->metrics.ascender >> 6;
|
||||||
const float font_ascent = (float)(face->size->metrics.ascender >> 6);
|
const float dpi_font_ascent = font_ascent / GetWindowScaleDPI().y;
|
||||||
float cursor_x = pos.x;
|
|
||||||
float cursor_y = pos.y + (font_ascent / dpi.y);
|
render_pos.y += dpi_font_ascent;
|
||||||
|
|
||||||
kbts_shape_context *Context = kbts_CreateShapeContext(nullptr, nullptr);
|
kbts_shape_context *Context = kbts_CreateShapeContext(nullptr, nullptr);
|
||||||
const kbts_font *kb_font = kbts_ShapePushFont(Context, &kbts);
|
const kbts_font *kb_font = kbts_ShapePushFont(Context, &kbts);
|
||||||
@ -138,36 +165,77 @@ void MyFont::render_text(const std::string_view text, const Vector2 pos, const C
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// ZoneNamedC()
|
{
|
||||||
// const zone2 = ztracy.ZoneNC(@src(), "ShapeUtf8", 0x00_ff_00_00);
|
ZoneScopedN("font")
|
||||||
// kb.kbts_ShapeBegin(Context, kb.KBTS_DIRECTION_DONT_KNOW, kb.KBTS_LANGUAGE_DONT_KNOW);
|
kbts_ShapeBegin(Context, KBTS_DIRECTION_DONT_KNOW, KBTS_LANGUAGE_DONT_KNOW);
|
||||||
// kb.kbts_ShapeUtf8(Context, text.ptr, @intCast(text.len), kb.KBTS_USER_ID_GENERATION_MODE_CODEPOINT_INDEX);
|
kbts_ShapeUtf8(Context, text.data(), text.size(), KBTS_USER_ID_GENERATION_MODE_CODEPOINT_INDEX);
|
||||||
// kb.kbts_ShapeEnd(Context);
|
kbts_ShapeEnd(Context);
|
||||||
// zone2.End();
|
}
|
||||||
|
|
||||||
// This is a simplified loop.
|
float cursor_x = 0;
|
||||||
// In your Zig code, you used 'kb' to get shaped runs.
|
float cursor_y = 0;
|
||||||
// Below is the logical equivalent for glyph placement:
|
|
||||||
for (char c : text) {
|
|
||||||
uint32_t glyph_index = FT_Get_Char_Index(face, c);
|
|
||||||
if (glyphs.count(glyph_index)) {
|
|
||||||
const Glyph& g = glyphs[glyph_index];
|
|
||||||
|
|
||||||
float x0 = cursor_x + g.dpi_bearing_x;
|
kbts_run Run;
|
||||||
float y0 = cursor_y - g.dpi_bearing_y;
|
while (my_kbts_ShapeRun(Context, &Run) != 0) {
|
||||||
float x1 = x0 + g.dpi_width;
|
ZoneScopedN("shape run")
|
||||||
float y1 = y0 + g.dpi_height;
|
if ((Run.Flags & KBTS_BREAK_FLAG_LINE_HARD) != 0) {
|
||||||
|
const float font_linegap = face->size->metrics.height >> 6;
|
||||||
|
const float dpi_font_linegap = font_linegap / GetWindowScaleDPI().y;
|
||||||
|
|
||||||
rlColor4ub(color.r, color.g, color.b, color.a);
|
cursor_y += dpi_font_linegap;
|
||||||
|
cursor_x = 0;
|
||||||
|
}
|
||||||
|
|
||||||
rlTexCoord2f(g.st0.x, g.st0.y); rlVertex2f(x0, y0);
|
kbts_glyph *RunGlyph;
|
||||||
rlTexCoord2f(g.st0.x, g.st1.y); rlVertex2f(x0, y1);
|
while (kbts_GlyphIteratorNext(&Run.Glyphs, &RunGlyph) != 0) {
|
||||||
rlTexCoord2f(g.st1.x, g.st1.y); rlVertex2f(x1, y1);
|
ZoneScopedN("glyph iterator")
|
||||||
rlTexCoord2f(g.st1.x, g.st0.y); rlVertex2f(x1, y0);
|
const int32_t CodepointIndex = RunGlyph->UserIdOrCodepointIndex;
|
||||||
|
kbts_shape_codepoint ShapeCodepoint;
|
||||||
|
if (kbts_ShapeGetShapeCodepoint(Context, CodepointIndex, &ShapeCodepoint) == 0) {
|
||||||
|
std::println("aah it's wrong!! idk how to handle the error rn!!");
|
||||||
|
}
|
||||||
|
|
||||||
// Advance (simplified, usually handled by HarfBuzz/kb)
|
const float advance_x = FT_MulFix(RunGlyph->AdvanceX, face->size->metrics.x_scale) >> 6;
|
||||||
FT_Load_Glyph(face, glyph_index, FT_LOAD_DEFAULT);
|
const float advance_y = FT_MulFix(RunGlyph->AdvanceY, face->size->metrics.y_scale) >> 6;
|
||||||
cursor_x += (float)(face->glyph->advance.x >> 6) / dpi.x;
|
const float dpi_advance_x = advance_x / GetWindowScaleDPI().x;
|
||||||
|
const float dpi_advance_y = advance_y / GetWindowScaleDPI().y;
|
||||||
|
|
||||||
|
const float offset_x = FT_MulFix(RunGlyph->OffsetX, face->size->metrics.x_scale) >> 6;
|
||||||
|
const float offset_y = FT_MulFix(RunGlyph->OffsetY, face->size->metrics.y_scale) >> 6;
|
||||||
|
const float dpi_offset_x = offset_x / GetWindowScaleDPI().x;
|
||||||
|
const float dpi_offset_y = offset_y / GetWindowScaleDPI().y;
|
||||||
|
|
||||||
|
if (auto it = glyphs.find(RunGlyph->Id); it != glyphs.end()) {
|
||||||
|
auto &glyph = it->second;
|
||||||
|
|
||||||
|
const Vector2 v0 = Vector2Add(render_pos, { .x = cursor_x + glyph.dpi_bearing_x + dpi_offset_x,
|
||||||
|
.y = cursor_y - glyph.dpi_bearing_y - dpi_offset_y });
|
||||||
|
|
||||||
|
const Vector2 v1 = Vector2Add(v0, Vector2{ .x = glyph.dpi_width, .y = glyph.dpi_height });
|
||||||
|
const Vector4 p0 = { .x = v0.x, .y = v0.y, .z = 0.0, .w = 1.0 };
|
||||||
|
const Vector4 p1 = { .x = v1.x, .y = v1.y, .z = 0.0, .w = 1.0 };
|
||||||
|
|
||||||
|
cursor_x += dpi_advance_x;
|
||||||
|
cursor_y += dpi_advance_y;
|
||||||
|
|
||||||
|
const Vector2 st0 = glyph.st0;
|
||||||
|
const Vector2 st1 = glyph.st1;
|
||||||
|
|
||||||
|
rlColor4ub(colour.r, colour.g, colour.b, colour.a);
|
||||||
|
rlNormal3f(0.0, 0.0, 1.0);
|
||||||
|
|
||||||
|
rlTexCoord2f(st0.x, st0.y); rlVertex2f(p0.x, p0.y);
|
||||||
|
rlTexCoord2f(st0.x, st1.y); rlVertex2f(p0.x, p1.y);
|
||||||
|
rlTexCoord2f(st1.x, st1.y); rlVertex2f(p1.x, p1.y);
|
||||||
|
rlTexCoord2f(st1.x, st0.y); rlVertex2f(p1.x, p0.y);
|
||||||
|
|
||||||
|
} else {
|
||||||
|
std::println("kb_text_shape found the glyph, but we didn't load it from the font. index {}",
|
||||||
|
RunGlyph->Id);
|
||||||
|
std::println("advance_x {}", advance_x);
|
||||||
|
cursor_x += dpi_advance_x;
|
||||||
|
cursor_y += dpi_advance_y;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -233,350 +301,3 @@ int32_t my_kbts_ShapeRun(kbts_shape_context *Context, kbts_run *Run) {
|
|||||||
|
|
||||||
return kbts_ShapeRun(Context, Run);
|
return kbts_ShapeRun(Context, Run);
|
||||||
}
|
}
|
||||||
|
|
||||||
// pub const Font = struct {
|
|
||||||
// face : ft.Face,
|
|
||||||
// glyphs : std.AutoHashMap(u32, Glyph),
|
|
||||||
// kbts_font : kb.kbts_font,
|
|
||||||
// // texture : c.Texture2D,
|
|
||||||
// texture : rl.Texture2D,
|
|
||||||
// kb_file_data : []u8,
|
|
||||||
//
|
|
||||||
// pub fn init(filename : [:0]const u8, size : i32, allocator: std.mem.Allocator) !Font {
|
|
||||||
//
|
|
||||||
// const file_data = try std.fs.cwd().readFileAlloc(
|
|
||||||
// allocator,
|
|
||||||
// filename,
|
|
||||||
// 10 * 1024 * 1024
|
|
||||||
// );
|
|
||||||
// defer allocator.free(file_data);
|
|
||||||
//
|
|
||||||
// const kb_file_data = try allocator.dupe(u8, file_data);
|
|
||||||
// errdefer allocator.free(kb_file_data);
|
|
||||||
//
|
|
||||||
// var face = try ft_lib.createFaceMemory(file_data, 0);
|
|
||||||
// var glyphs = std.AutoHashMap(u32, Glyph).init(allocator);
|
|
||||||
// try face.setCharSize(0, size * 64, 0, 96 * @as(u16, @intFromFloat(rl.getWindowScaleDPI().y)));
|
|
||||||
// try face.selectCharmap(.unicode);
|
|
||||||
//
|
|
||||||
// var rects = try std.ArrayList(rp.stbrp_rect).initCapacity(allocator, 1024);
|
|
||||||
// defer rects.deinit(allocator);
|
|
||||||
//
|
|
||||||
// var nodes : [ATLAS_SIZE]rp.stbrp_node = std.mem.zeroes([ATLAS_SIZE]rp.stbrp_node);
|
|
||||||
//
|
|
||||||
// var stbrpcontext : rp.stbrp_context = .{};
|
|
||||||
// rp.stbrp_init_target(&stbrpcontext, ATLAS_SIZE, ATLAS_SIZE, &nodes, nodes.len);
|
|
||||||
//
|
|
||||||
// const _atlas : []u8 = try allocator.alloc(u8, ATLAS_SIZE * ATLAS_SIZE);
|
|
||||||
// defer allocator.free(_atlas);
|
|
||||||
// @memset(_atlas, 0);
|
|
||||||
//
|
|
||||||
// const atlas : rl.Image = .{
|
|
||||||
// .data = _atlas.ptr,
|
|
||||||
// .width = ATLAS_SIZE,
|
|
||||||
// .height = ATLAS_SIZE,
|
|
||||||
// .mipmaps = 1,
|
|
||||||
// .format = rl.PixelFormat.uncompressed_grayscale,
|
|
||||||
// };
|
|
||||||
//
|
|
||||||
// for (0..face.numGlyphs()) |index| {
|
|
||||||
// try face.loadGlyph(@intCast(index), .{});
|
|
||||||
// const bmp = face.glyph().bitmap();
|
|
||||||
//
|
|
||||||
// try rects.append(allocator, .{
|
|
||||||
// .id = @intCast(index),//@intCast(face.glyph().glyphIndex()),
|
|
||||||
// .w = @max(1, @as(c_int, @intCast(bmp.width()))),
|
|
||||||
// .h = @max(1, @as(c_int, @intCast(bmp.rows()))),
|
|
||||||
// .x = 0,
|
|
||||||
// .y = 0,
|
|
||||||
// .was_packed = 0,
|
|
||||||
// });
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// _ = rp.stbrp_pack_rects(&stbrpcontext, rects.items.ptr, @intCast(rects.items.len));
|
|
||||||
//
|
|
||||||
// for (rects.items) |rect| {
|
|
||||||
// const index : u32 = @intCast(rect.id);
|
|
||||||
// if (rect.was_packed == 0) continue;
|
|
||||||
// try face.loadGlyph(index, .{ .render = true });
|
|
||||||
//
|
|
||||||
// const bmp = face.glyph().bitmap();
|
|
||||||
//
|
|
||||||
// const pitch: usize = @intCast(bmp.pitch());
|
|
||||||
// const w: usize = @intCast(bmp.width());
|
|
||||||
// const h: usize = @intCast(bmp.rows());
|
|
||||||
//
|
|
||||||
// const dst_x: usize = @intCast(rect.x);
|
|
||||||
// const dst_y: usize = @intCast(rect.y);
|
|
||||||
//
|
|
||||||
// if (bmp.buffer()) |buf| {
|
|
||||||
// for (0..h) |y| {
|
|
||||||
// const src = buf[y * pitch .. y * pitch + w];
|
|
||||||
//
|
|
||||||
// const dst_index = (dst_y + y) * ATLAS_SIZE + dst_x;
|
|
||||||
// const dst = _atlas[dst_index .. dst_index + w];
|
|
||||||
//
|
|
||||||
// @memcpy(dst, src);
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// const width : i32 = @intCast(bmp.width());
|
|
||||||
// const height : i32 = @intCast(bmp.rows());
|
|
||||||
// const dpi_width : f32 = @as(f32, @floatFromInt(width)) / rl.getWindowScaleDPI().x;
|
|
||||||
// const dpi_height : f32 = @as(f32, @floatFromInt(height)) / rl.getWindowScaleDPI().y;
|
|
||||||
// const bearing_x : i32 = face.glyph().bitmapLeft();
|
|
||||||
// const bearing_y : i32 = face.glyph().bitmapTop();
|
|
||||||
// const dpi_bearing_x : f32 = @as(f32, @floatFromInt(bearing_x)) / rl.getWindowScaleDPI().x;
|
|
||||||
// const dpi_bearing_y : f32 = @as(f32, @floatFromInt(bearing_y)) / rl.getWindowScaleDPI().y;
|
|
||||||
// const descent : i32 = height - bearing_y;
|
|
||||||
// const ascent : i32 = height - descent;
|
|
||||||
// const dpi_descent : f32 = dpi_height - dpi_bearing_y;
|
|
||||||
// const dpi_ascent : f32 = dpi_height - dpi_descent;
|
|
||||||
//
|
|
||||||
// const x : i16 = @intCast(rect.x);
|
|
||||||
// const y : i16 = @as(i16, @intCast(rect.y)) + @as(i16, @intCast(height));
|
|
||||||
//
|
|
||||||
// const fx = @as(f32, @floatFromInt(x));
|
|
||||||
// const fy = @as(f32, @floatFromInt(y));
|
|
||||||
// const fw = @as(f32, @floatFromInt(width));
|
|
||||||
// const fh = @as(f32, @floatFromInt(height));
|
|
||||||
// const fs = @as(f32, ATLAS_SIZE);
|
|
||||||
//
|
|
||||||
// const glyph = Glyph{
|
|
||||||
// .x = x,
|
|
||||||
// .y = y,
|
|
||||||
// .index = index,
|
|
||||||
// .bearing_x = bearing_x,
|
|
||||||
// .bearing_y = bearing_y,
|
|
||||||
// .dpi_bearing_x = dpi_bearing_x,
|
|
||||||
// .dpi_bearing_y = dpi_bearing_y,
|
|
||||||
// .width = width,
|
|
||||||
// .height = height,
|
|
||||||
// .dpi_width = dpi_width,
|
|
||||||
// .dpi_height = dpi_height,
|
|
||||||
// .descent = descent,
|
|
||||||
// .ascent = ascent,
|
|
||||||
// .dpi_descent = dpi_descent,
|
|
||||||
// .dpi_ascent = dpi_ascent,
|
|
||||||
// .st0 = .{.x = (fx + 0.5) / fs, .y = (fy - fh + 0.5) / fs},
|
|
||||||
// .st1 = .{.x = (fx + fw - 0.5) / fs, .y = (fy - 0.5) / fs},
|
|
||||||
// };
|
|
||||||
//
|
|
||||||
// try glyphs.put(glyph.index, glyph);
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// const texture = try rl.loadTextureFromImage(atlas);
|
|
||||||
//
|
|
||||||
// var kbts_font = kb.kbts_FontFromMemory(kb_file_data.ptr, @intCast(kb_file_data.len), 0, null, null);
|
|
||||||
//
|
|
||||||
// if (kb.kbts_FontIsValid(&kbts_font) == 0) {
|
|
||||||
// std.log.info("[Error] [kb_text_shape] Failed to load the font.", .{});
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// const hb_blob = hb.Blob.initFromFile(filename);
|
|
||||||
// _ = hb_blob;
|
|
||||||
//
|
|
||||||
// return .{
|
|
||||||
// .face = face,
|
|
||||||
// .glyphs = glyphs,
|
|
||||||
// .kbts_font = kbts_font,
|
|
||||||
// .texture = texture,
|
|
||||||
// .kb_file_data = kb_file_data,
|
|
||||||
// };
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// pub fn deinit(self: *Font, allocator : std.mem.Allocator) void {
|
|
||||||
// self.glyphs.deinit();
|
|
||||||
// self.face.deinit();
|
|
||||||
// kb.kbts_FreeFont(&self.kbts_font);
|
|
||||||
// self.texture.unload();
|
|
||||||
// allocator.free(self.kb_file_data);
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// pub fn render_text(
|
|
||||||
// self: *Font,
|
|
||||||
// text: []const u8,
|
|
||||||
// pos: rl.Vector2,
|
|
||||||
// window_space: bool,
|
|
||||||
// colour: rl.Color,
|
|
||||||
// background: rl.Color,
|
|
||||||
// nice_background: bool,
|
|
||||||
// count_descent: bool
|
|
||||||
// ) void {
|
|
||||||
// if (text.len == 0)
|
|
||||||
// return;
|
|
||||||
//
|
|
||||||
// const zone = ztracy.ZoneNC(@src(), "render_text", 0x00_ff_00_00);
|
|
||||||
// defer zone.End();
|
|
||||||
//
|
|
||||||
// rl.beginShaderMode(shader);
|
|
||||||
// rl.gl.rlSetTexture(self.texture.id);
|
|
||||||
// rl.gl.rlBegin(rl.gl.rl_quads);
|
|
||||||
//
|
|
||||||
// if (nice_background) {
|
|
||||||
// self.render_text(
|
|
||||||
// text,
|
|
||||||
// pos.add(.{.x = 3.0, .y = -3.0}),
|
|
||||||
// window_space,
|
|
||||||
// rl.Color{ .r = 0, .g = 0, .b = 0, .a = 255 },
|
|
||||||
// rl.Color{ .r = 0, .g = 0, .b = 0, .a = 0 },
|
|
||||||
// false,
|
|
||||||
// false
|
|
||||||
// );
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// var render_pos = pos;
|
|
||||||
// _ = count_descent;
|
|
||||||
// _ = background;
|
|
||||||
//
|
|
||||||
// const font_ascent : f32 = @floatFromInt(self.face.size().metrics().ascender >> 6);
|
|
||||||
// const dpi_font_ascent = font_ascent / rl.getWindowScaleDPI().y;
|
|
||||||
//
|
|
||||||
// render_pos.y += dpi_font_ascent;
|
|
||||||
//
|
|
||||||
// const Context = kb.kbts_CreateShapeContext(null, null);
|
|
||||||
// defer kb.kbts_DestroyShapeContext(Context);
|
|
||||||
// const kb_font = kb.kbts_ShapePushFont(Context, &self.kbts_font);
|
|
||||||
// if (kb_font == null) {
|
|
||||||
// std.log.info("Could not open font!", .{});
|
|
||||||
// return;
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// const zone2 = ztracy.ZoneNC(@src(), "ShapeUtf8", 0x00_ff_00_00);
|
|
||||||
// kb.kbts_ShapeBegin(Context, kb.KBTS_DIRECTION_DONT_KNOW, kb.KBTS_LANGUAGE_DONT_KNOW);
|
|
||||||
// kb.kbts_ShapeUtf8(Context, text.ptr, @intCast(text.len), kb.KBTS_USER_ID_GENERATION_MODE_CODEPOINT_INDEX);
|
|
||||||
// kb.kbts_ShapeEnd(Context);
|
|
||||||
// zone2.End();
|
|
||||||
//
|
|
||||||
// var cursor_x : f32 = 0;
|
|
||||||
// var cursor_y : f32 = 0;
|
|
||||||
//
|
|
||||||
// var Run = kb.kbts_run{};
|
|
||||||
// while (my_kbts_ShapeRun(Context, &Run) != 0) {
|
|
||||||
// const zone3 = ztracy.ZoneNC(@src(), "shape run", 0x00_ff_00_00);
|
|
||||||
// defer zone3.End();
|
|
||||||
// if ((Run.Flags & kb.KBTS_BREAK_FLAG_LINE_HARD) != 0) {
|
|
||||||
// const font_linegap : f32 = @floatFromInt(self.face.size().metrics().height >> 6);
|
|
||||||
// const dpi_font_linegap = font_linegap / rl.getWindowScaleDPI().y;
|
|
||||||
//
|
|
||||||
// cursor_y += dpi_font_linegap;
|
|
||||||
// cursor_x = 0;
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// var g : [*c]kb.kbts_glyph = null;
|
|
||||||
// while (kb.kbts_GlyphIteratorNext(&Run.Glyphs, &g) != 0) {
|
|
||||||
// const zone4 = ztracy.ZoneNC(@src(), "glyph iterator", 0x00_ff_00_00);
|
|
||||||
// defer zone4.End();
|
|
||||||
// const RunGlyph : *kb.kbts_glyph = g.?;
|
|
||||||
// const CodepointIndex : i32 = RunGlyph.UserIdOrCodepointIndex;
|
|
||||||
// var ShapeCodepoint : kb.kbts_shape_codepoint = undefined;
|
|
||||||
// if (kb.kbts_ShapeGetShapeCodepoint(Context, CodepointIndex, &ShapeCodepoint) == 0) {
|
|
||||||
// std.log.info("aah it's wrong!! idk how to handle the error rn!!", .{});
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// const advance_x : f32 = @floatFromInt(ft.mulFix(RunGlyph.AdvanceX, @intCast(self.face.size().metrics().x_scale)) >> 6);
|
|
||||||
// const advance_y : f32 = @floatFromInt(ft.mulFix(RunGlyph.AdvanceY, @intCast(self.face.size().metrics().y_scale)) >> 6);
|
|
||||||
// const dpi_advance_x = advance_x / rl.getWindowScaleDPI().x;
|
|
||||||
// const dpi_advance_y = advance_y / rl.getWindowScaleDPI().y;
|
|
||||||
//
|
|
||||||
// const offset_x : f32 = @floatFromInt(ft.mulFix(RunGlyph.OffsetX, @intCast(self.face.size().metrics().x_scale)) >> 6);
|
|
||||||
// const offset_y : f32 = @floatFromInt(ft.mulFix(RunGlyph.OffsetY, @intCast(self.face.size().metrics().y_scale)) >> 6);
|
|
||||||
// const dpi_offset_x = offset_x / rl.getWindowScaleDPI().x;
|
|
||||||
// const dpi_offset_y = offset_y / rl.getWindowScaleDPI().y;
|
|
||||||
//
|
|
||||||
// if (self.glyphs.getPtr(RunGlyph.Id)) |glyph| {
|
|
||||||
// if (RunGlyph.OffsetX != 0) {
|
|
||||||
// std.log.info("font bearing ({}, {}), kb offset ({}, {})", .{glyph.bearing_x, glyph.bearing_y, RunGlyph.OffsetX, RunGlyph.OffsetX});
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// var v0 = rl.Vector2.zero();
|
|
||||||
// var v1 = rl.Vector2.zero();
|
|
||||||
//
|
|
||||||
// v0 = render_pos.add(.{ .x = cursor_x + glyph.dpi_bearing_x + dpi_offset_x,
|
|
||||||
// .y = cursor_y - glyph.dpi_bearing_y - dpi_offset_y });
|
|
||||||
//
|
|
||||||
// v1 = v0.add(rl.Vector2{ .x = glyph.dpi_width, .y = glyph.dpi_height });
|
|
||||||
// const p0 : rl.Vector4 = .{ .x = v0.x, .y = v0.y, .z = 0.0, .w = 1.0 };
|
|
||||||
// const p1 : rl.Vector4 = .{ .x = v1.x, .y = v1.y, .z = 0.0, .w = 1.0 };
|
|
||||||
//
|
|
||||||
// cursor_x += dpi_advance_x;
|
|
||||||
// cursor_y += dpi_advance_y;
|
|
||||||
//
|
|
||||||
// const st0 = glyph.st0;
|
|
||||||
// const st1 = glyph.st1;
|
|
||||||
//
|
|
||||||
// rl.gl.rlColor4ub(colour.r, colour.g, colour.b, colour.a);
|
|
||||||
// rl.gl.rlNormal3f(0.0, 0.0, 1.0);
|
|
||||||
//
|
|
||||||
// rl.gl.rlTexCoord2f(st0.x, st0.y); rl.gl.rlVertex2f(p0.x, p0.y);
|
|
||||||
// rl.gl.rlTexCoord2f(st0.x, st1.y); rl.gl.rlVertex2f(p0.x, p1.y);
|
|
||||||
// rl.gl.rlTexCoord2f(st1.x, st1.y); rl.gl.rlVertex2f(p1.x, p1.y);
|
|
||||||
// rl.gl.rlTexCoord2f(st1.x, st0.y); rl.gl.rlVertex2f(p1.x, p0.y);
|
|
||||||
//
|
|
||||||
// } else {
|
|
||||||
// std.log.warn("kb_text_shape found the glyph, but we didn't load it from the font. index {}", .{RunGlyph.Id});
|
|
||||||
// std.log.warn("advance_x {}", .{advance_x});
|
|
||||||
// cursor_x += dpi_advance_x;
|
|
||||||
// cursor_y += dpi_advance_y;
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// rl.gl.rlEnd();
|
|
||||||
// rl.gl.rlSetTexture(0);
|
|
||||||
// rl.endShaderMode();
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// pub fn size_row(self: *Font, str: []const u8, n: i32, max_width: f32) struct {rl.Vector2, f32, i32} {
|
|
||||||
// _ = max_width;
|
|
||||||
// _ = n;
|
|
||||||
// const Context = kb.kbts_CreateShapeContext(null, null);
|
|
||||||
// const kb_font = kb.kbts_ShapePushFont(Context, &self.kb);
|
|
||||||
// if (kb_font == null) {
|
|
||||||
// std.log.info("Could not open font!", .{});
|
|
||||||
// return .{ rl.Vector2.zero(), 0, 0 };
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// kb.kbts_ShapeBegin(Context, kb.KBTS_DIRECTION_DONT_KNOW, kb.KBTS_LANGUAGE_DONT_KNOW);
|
|
||||||
// kb.kbts_ShapeUtf8(Context, str.ptr, @intCast(str.len), kb.KBTS_USER_ID_GENERATION_MODE_CODEPOINT_INDEX);
|
|
||||||
// kb.kbts_ShapeEnd(Context);
|
|
||||||
//
|
|
||||||
// var size = rl.Vector2.zero();
|
|
||||||
// var max_descent : f32 = 0;
|
|
||||||
//
|
|
||||||
// var Run = kb.kbts_run{};
|
|
||||||
// while(kb.kbts_ShapeRun(Context, &Run) != 0) {
|
|
||||||
// if ((Run.Flags & kb.KBTS_BREAK_FLAG_LINE_HARD) != 0) {
|
|
||||||
//
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// var g : [*c]kb.kbts_glyph = null;
|
|
||||||
// while (kb.kbts_GlyphIteratorNext(&Run.Glyphs, &g) != 0) {
|
|
||||||
// const RunGlyph : *kb.kbts_glyph = g.?;
|
|
||||||
// const CodepointIndex : i32 = RunGlyph.UserIdOrCodepointIndex;
|
|
||||||
// var ShapeCodepoint : kb.kbts_shape_codepoint = undefined;
|
|
||||||
// if (kb.kbts_ShapeGetShapeCodepoint(Context, CodepointIndex, &ShapeCodepoint) == 0) {
|
|
||||||
// std.log.info("aah it's wrong!! idk how to handle the error rn!!", .{});
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// if (self.glyphs.getPtr(@intCast(RunGlyph.Id))) |glyph| {
|
|
||||||
// const advance_x = @as(f32, @floatFromInt(ft.mulFix(RunGlyph.AdvanceX, @intCast(self.face.size().metrics().x_scale)) >> 6));
|
|
||||||
// const dpi_advance_x = advance_x / rl.getWindowScaleDPI().x;
|
|
||||||
//
|
|
||||||
// size.y = @max(size.y, glyph.dpi_height);
|
|
||||||
// size.x += dpi_advance_x;
|
|
||||||
// max_descent = @max(max_descent, glyph.dpi_descent);
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// return .{ size, max_descent, 0};
|
|
||||||
// }
|
|
||||||
// };
|
|
||||||
//
|
|
||||||
// fn my_kbts_ShapeRun(Context: ?*kb.kbts_shape_context, Run: [*c]kb.kbts_run) c_int {
|
|
||||||
// const zone = ztracy.ZoneNC(@src(), "my_kbts_ShapeRun", 0x00_ff_00_00);
|
|
||||||
// defer zone.End();
|
|
||||||
// return kb.kbts_ShapeRun(Context, Run);
|
|
||||||
// }
|
|
||||||
|
|
||||||
|
|||||||
@ -35,13 +35,13 @@ struct MyFont {
|
|||||||
FT_Face face;
|
FT_Face face;
|
||||||
std::unordered_map<uint32_t, Glyph> glyphs;
|
std::unordered_map<uint32_t, Glyph> glyphs;
|
||||||
Texture2D texture;
|
Texture2D texture;
|
||||||
std::vector<uint8_t> font_data;
|
std::vector<uint8_t> kb_file_data;
|
||||||
kbts_font kbts;
|
kbts_font kbts;
|
||||||
|
|
||||||
MyFont(const std::string& filename, int size);
|
MyFont(const std::string& filename, int size);
|
||||||
void deinit();
|
void deinit();
|
||||||
|
|
||||||
void render_text(const std::string_view text, const Vector2 pos, const Color color);
|
void render_text(std::string_view text, Vector2 pos, Color color);
|
||||||
|
|
||||||
struct size_ret {
|
struct size_ret {
|
||||||
Vector2 size;
|
Vector2 size;
|
||||||
|
|||||||
15
src/main.cpp
15
src/main.cpp
@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
#include <raylib.h>
|
#include <raylib.h>
|
||||||
#include <freetype/freetype.h>
|
#include <freetype/freetype.h>
|
||||||
#include <harfbuzz/hb.h>
|
#include <hb.h>
|
||||||
|
|
||||||
#include "font.h"
|
#include "font.h"
|
||||||
#include "misc.h"
|
#include "misc.h"
|
||||||
@ -28,12 +28,13 @@ int main() {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const int32_t screenwidth = 2560;
|
const int32_t screenwidth = 1280;
|
||||||
const int32_t screenheight = 1440;
|
const int32_t screenheight = 720;
|
||||||
|
|
||||||
InitWindow(screenwidth, screenheight, "raylib");
|
InitWindow(screenwidth, screenheight, "raylib");
|
||||||
|
|
||||||
MyFont vollkorn("assets/fonts/Vollkorn/static/Vollkorn-Regular.ttf", 42);
|
MyFont vollkorn("assets/fonts/Vollkorn/static/Vollkorn-Regular.ttf", 42);
|
||||||
|
MyFont arabic("assets/fonts/Amiri/Amiri-Regular.ttf", 28);
|
||||||
shader = LoadShader(nullptr, "assets/text.frag");
|
shader = LoadShader(nullptr, "assets/text.frag");
|
||||||
|
|
||||||
float old_time = GetTime();
|
float old_time = GetTime();
|
||||||
@ -59,18 +60,22 @@ int main() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
auto [x, y] = GetWindowScaleDPI();
|
auto [x, y] = GetWindowScaleDPI();
|
||||||
std::printf("(%f, %f)\n", x, y);
|
|
||||||
BeginDrawing();
|
BeginDrawing();
|
||||||
ClearBackground(SKYBLUE);
|
ClearBackground(SKYBLUE);
|
||||||
//DrawText("Hello, Sailor!", 150, 150, 20, RAYWHITE);
|
//DrawText("Hello, Sailor!", 150, 150, 20, RAYWHITE);
|
||||||
|
|
||||||
vollkorn.render_text("The night is long and cold outside", {0 ,0}, WHITE);
|
// vollkorn.render_text("The night is long and cold outside", {0 ,0}, WHITE);
|
||||||
|
|
||||||
|
arabic.render_text("الليل طويل وبارد في الخارج", Vector2{ .x = 0, .y = 100}, WHITE);
|
||||||
|
|
||||||
misc::drawFPS(0, 0, frame_time);
|
misc::drawFPS(0, 0, frame_time);
|
||||||
|
|
||||||
EndDrawing();
|
EndDrawing();
|
||||||
|
|
||||||
|
{
|
||||||
|
ZoneScopedN("SwapScreenBuffer")
|
||||||
SwapScreenBuffer();
|
SwapScreenBuffer();
|
||||||
|
}
|
||||||
|
|
||||||
frame++;
|
frame++;
|
||||||
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user