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 }