139 lines
4.4 KiB
Zig
139 lines
4.4 KiB
Zig
const std = @import("std");
|
|
const rl = @import("raylib");
|
|
|
|
font: rl.Font,
|
|
spacing: ?f32 = null,
|
|
line_height: f32 = 1.4,
|
|
|
|
pub fn getSpacing(self: @This()) f32 {
|
|
if (self.spacing) |spacing| {
|
|
return spacing;
|
|
} else {
|
|
return self.getSize() / 10;
|
|
}
|
|
}
|
|
|
|
pub fn getSize(self: @This()) f32 {
|
|
return @floatFromInt(self.font.baseSize);
|
|
}
|
|
|
|
pub fn drawTextLines(self: @This(), lines: []const []const u8, position: rl.Vector2, tint: rl.Color) void {
|
|
var offset_y: f32 = 0;
|
|
|
|
const font_size = self.getSize();
|
|
|
|
for (lines) |line| {
|
|
self.drawText(line, position.add(.{ .x = 0, .y = offset_y }), tint);
|
|
|
|
const line_size = self.measureText(line);
|
|
offset_y += line_size.y + font_size * (self.line_height - 1);
|
|
}
|
|
}
|
|
|
|
pub fn measureTextLines(self: @This(), lines: []const []const u8) rl.Vector2 {
|
|
var text_size = rl.Vector2.zero();
|
|
|
|
const font_size = self.getSize();
|
|
|
|
for (lines) |line| {
|
|
const line_size = self.measureText(line);
|
|
|
|
text_size.x = @max(text_size.x, line_size.x);
|
|
text_size.y += line_size.y;
|
|
}
|
|
|
|
text_size.y += (self.line_height - 1) * font_size * @as(f32, @floatFromInt(@max(lines.len - 1, 0)));
|
|
|
|
return text_size;
|
|
}
|
|
|
|
pub fn drawTextEx(self: @This(), text: []const u8, position: rl.Vector2, tint: rl.Color, offset: *rl.Vector2) void {
|
|
if (self.font.texture.id == 0) return;
|
|
|
|
const font_size = self.getSize();
|
|
const spacing = self.getSpacing();
|
|
|
|
var iter = std.unicode.Utf8Iterator{ .bytes = text, .i = 0 };
|
|
while (iter.nextCodepoint()) |codepoint| {
|
|
if (codepoint == '\n') {
|
|
offset.x = 0;
|
|
offset.y += font_size * self.line_height;
|
|
} else {
|
|
if (!(codepoint <= 255 and std.ascii.isWhitespace(@intCast(codepoint)))) {
|
|
var codepoint_position = position.add(offset.*);
|
|
codepoint_position.x = @round(codepoint_position.x);
|
|
codepoint_position.y = @round(codepoint_position.y);
|
|
rl.drawTextCodepoint(self.font, codepoint, codepoint_position, font_size, tint);
|
|
}
|
|
|
|
const index: u32 = @intCast(rl.getGlyphIndex(self.font, codepoint));
|
|
if (self.font.glyphs[index].advanceX != 0) {
|
|
offset.x += @floatFromInt(self.font.glyphs[index].advanceX);
|
|
} else {
|
|
offset.x += self.font.recs[index].width;
|
|
offset.x += @floatFromInt(self.font.glyphs[index].offsetX);
|
|
}
|
|
offset.x += spacing;
|
|
}
|
|
}
|
|
}
|
|
|
|
pub fn drawText(self: @This(), text: []const u8, position: rl.Vector2, tint: rl.Color) void {
|
|
var offset = rl.Vector2.init(0, 0);
|
|
self.drawTextEx(text, position, tint, &offset);
|
|
}
|
|
|
|
pub fn drawTextAlloc(self: @This(), allocator: std.mem.Allocator, comptime fmt: []const u8, args: anytype, position: rl.Vector2, tint: rl.Color) !void {
|
|
const text = try std.fmt.allocPrint(allocator, fmt, args);
|
|
defer allocator.free(text);
|
|
|
|
self.drawText(text, position, tint);
|
|
}
|
|
|
|
pub fn measureText(self: @This(), text: []const u8) rl.Vector2 {
|
|
var text_size = rl.Vector2.zero();
|
|
|
|
if (self.font.texture.id == 0) return text_size; // Security check
|
|
if (text.len == 0) return text_size;
|
|
|
|
const font_size = self.getSize();
|
|
const spacing = self.getSpacing();
|
|
|
|
var line_width: f32 = 0;
|
|
text_size.y = font_size;
|
|
|
|
var iter = std.unicode.Utf8Iterator{ .bytes = text, .i = 0 };
|
|
while (iter.nextCodepoint()) |codepoint| {
|
|
if (codepoint == '\n') {
|
|
text_size.y += font_size * self.line_height;
|
|
|
|
line_width = 0;
|
|
} else {
|
|
if (line_width > 0) {
|
|
line_width += spacing;
|
|
}
|
|
|
|
const index: u32 = @intCast(rl.getGlyphIndex(self.font, codepoint));
|
|
if (self.font.glyphs[index].advanceX != 0) {
|
|
line_width += @floatFromInt(self.font.glyphs[index].advanceX);
|
|
} else {
|
|
line_width += self.font.recs[index].width;
|
|
line_width += @floatFromInt(self.font.glyphs[index].offsetX);
|
|
}
|
|
|
|
text_size.x = @max(text_size.x, line_width);
|
|
}
|
|
}
|
|
|
|
return text_size;
|
|
}
|
|
|
|
pub fn drawTextCenter(self: @This(), text: []const u8, position: rl.Vector2, tint: rl.Color) void {
|
|
const text_size = self.measureText(text);
|
|
const adjusted_position = rl.Vector2{
|
|
.x = position.x - text_size.x / 2,
|
|
.y = position.y - text_size.y / 2,
|
|
};
|
|
self.drawText(text, adjusted_position, tint);
|
|
}
|