lib/ui/src/asset/capacity.zig
daab053ee43316e1809a84551d573ddd1e5bf3d2
1 const std = @import("std");
2 const model = @import("model.zig");
3
4 pub const family_bytes_per_font: u32 = 64;
5 pub const default_table_bytes: usize = 47_104;
6
7 pub const Limits = struct {
8 fonts: u32 = 32,
9 images: u32 = 16,
10 owned_bytes: u32 = 41_328,
11 };
12
13 pub const Error = error{CapacityOverflow};
14
15 pub const Capacity = struct {
16 total_bytes: usize,
17 font_bytes: usize,
18 image_bytes: usize,
19 string_bytes: usize,
20 owned_bytes: usize,
21
22 pub fn derive(limits: Limits) Error!Capacity {
23 if (limits.fonts > std.math.maxInt(u32) / family_bytes_per_font) return error.CapacityOverflow;
24 const FontDescriptor = model.FontDescriptor;
25 const ImageDescriptor = model.ImageDescriptor;
26 const Bytes = model.Bytes;
27 const font_count: usize = limits.fonts;
28 const image_count: usize = limits.images;
29 var cursor: usize = 0;
30 try addSlice(&cursor, FontDescriptor, font_count);
31 try addSlice(&cursor, Bytes, font_count);
32 try addSlice(&cursor, u32, font_count);
33 try addSlice(&cursor, u64, std.math.divCeil(usize, font_count, 64) catch unreachable);
34 try addSlice(&cursor, ImageDescriptor, image_count);
35 try addSlice(&cursor, Bytes, image_count);
36 try addSlice(&cursor, u32, image_count);
37 try addSlice(&cursor, u64, std.math.divCeil(usize, image_count, 64) catch unreachable);
38 const string_bytes = std.math.mul(usize, font_count, family_bytes_per_font) catch return error.CapacityOverflow;
39 try addSlice(&cursor, u8, string_bytes);
40 try addSlice(&cursor, u8, limits.owned_bytes);
41 return .{
42 .total_bytes = cursor,
43 .font_bytes = std.math.mul(usize, font_count, @sizeOf(FontDescriptor)) catch unreachable,
44 .image_bytes = std.math.mul(usize, image_count, @sizeOf(ImageDescriptor)) catch unreachable,
45 .string_bytes = string_bytes,
46 .owned_bytes = limits.owned_bytes,
47 };
48 }
49 };
50
51 fn addSlice(cursor: *usize, comptime T: type, count: usize) Error!void {
52 const rounded = std.math.add(usize, cursor.*, @alignOf(T) - 1) catch return error.CapacityOverflow;
53 const aligned = rounded & ~(@as(usize, @alignOf(T)) - 1);
54 const bytes = std.math.mul(usize, count, @sizeOf(T)) catch return error.CapacityOverflow;
55 cursor.* = std.math.add(usize, aligned, bytes) catch return error.CapacityOverflow;
56 }