this repo has no description
13
fork

Configure Feed

Select the types of activity you want to include in your feed.

at b58ae3a2fa16b3b7f11d2a7297c73a1e839d035b 188 lines 5.8 kB view raw
1const std = @import("std"); 2const fmt = std.fmt; 3const math = std.math; 4const base64 = std.base64.standard.Encoder; 5const zigimg = @import("zigimg"); 6 7const Window = @import("Window.zig"); 8 9const Image = @This(); 10 11const transmit_opener = "\x1b_Gf=32,i={d},s={d},v={d},m={d};"; 12 13pub const Source = union(enum) { 14 path: []const u8, 15 mem: []const u8, 16}; 17 18pub const TransmitFormat = enum { 19 rgb, 20 rgba, 21 png, 22}; 23 24pub const TransmitMedium = enum { 25 file, 26 temp_file, 27 shared_mem, 28}; 29 30pub const Placement = struct { 31 img_id: u32, 32 options: Image.DrawOptions, 33}; 34 35pub const CellSize = struct { 36 rows: u16, 37 cols: u16, 38}; 39 40pub const DrawOptions = struct { 41 /// an offset into the top left cell, in pixels, with where to place the 42 /// origin of the image. These must be less than the pixel size of a single 43 /// cell 44 pixel_offset: ?struct { 45 x: u16, 46 y: u16, 47 } = null, 48 /// the vertical stacking order 49 /// < 0: Drawn beneath text 50 /// < -1_073_741_824: Drawn beneath "default" background cells 51 z_index: ?i32 = null, 52 /// A clip region of the source image to draw. 53 clip_region: ?struct { 54 x: ?u16 = null, 55 y: ?u16 = null, 56 width: ?u16 = null, 57 height: ?u16 = null, 58 } = null, 59 /// Scaling to apply to the Image 60 scale: enum { 61 /// no scaling applied. the image may extend beyond the window 62 none, 63 /// Stretch / shrink the image to fill the window 64 fill, 65 /// Scale the image to fit the window, maintaining aspect ratio 66 fit, 67 /// Scale the image to fit the window, only if needed. 68 contain, 69 } = .none, 70 /// the size to render the image. Generally you will not need to use this 71 /// field, and should prefer to use scale. `draw` will fill in this field with 72 /// the correct values if a scale method is applied. 73 size: ?struct { 74 rows: ?u16 = null, 75 cols: ?u16 = null, 76 } = null, 77}; 78 79/// unique identifier for this image. This will be managed by the screen. 80id: u32, 81 82/// width in pixels 83width: u16, 84/// height in pixels 85height: u16, 86 87pub fn draw(self: Image, win: Window, opts: DrawOptions) !void { 88 var p_opts = opts; 89 switch (opts.scale) { 90 .none => {}, 91 .fill => { 92 p_opts.size = .{ 93 .rows = win.height, 94 .cols = win.width, 95 }; 96 }, 97 .fit, 98 .contain, 99 => contain: { 100 // cell geometry 101 const x_pix = win.screen.width_pix; 102 const y_pix = win.screen.height_pix; 103 const w = win.screen.width; 104 const h = win.screen.height; 105 106 const pix_per_col = try std.math.divCeil(usize, x_pix, w); 107 const pix_per_row = try std.math.divCeil(usize, y_pix, h); 108 109 const win_width_pix = pix_per_col * win.width; 110 const win_height_pix = pix_per_row * win.height; 111 112 const fit_x: bool = if (win_width_pix >= self.width) true else false; 113 const fit_y: bool = if (win_height_pix >= self.height) true else false; 114 115 // Does the image fit with no scaling? 116 if (opts.scale == .contain and fit_x and fit_y) break :contain; 117 118 // Does the image require vertical scaling? 119 if (fit_x and !fit_y) 120 p_opts.size = .{ 121 .rows = win.height, 122 } 123 124 // Does the image require horizontal scaling? 125 else if (!fit_x and fit_y) 126 p_opts.size = .{ 127 .cols = win.width, 128 } 129 else if (!fit_x and !fit_y) { 130 const diff_x = self.width - win_width_pix; 131 const diff_y = self.height - win_height_pix; 132 // The width difference is larger than the height difference. 133 // Scale by width 134 if (diff_x > diff_y) 135 p_opts.size = .{ 136 .cols = win.width, 137 } 138 else 139 // The height difference is larger than the width difference. 140 // Scale by height 141 p_opts.size = .{ 142 .rows = win.height, 143 }; 144 } else { 145 std.debug.assert(opts.scale == .fit); 146 std.debug.assert(win_width_pix >= self.width); 147 std.debug.assert(win_height_pix >= self.height); 148 149 // Fits in both directions. Find the closer direction 150 const diff_x = win_width_pix - self.width; 151 const diff_y = win_height_pix - self.height; 152 // The width is closer in dimension. Scale by that 153 if (diff_x < diff_y) 154 p_opts.size = .{ 155 .cols = win.width, 156 } 157 else 158 p_opts.size = .{ 159 .rows = win.height, 160 }; 161 } 162 }, 163 } 164 const p = Placement{ 165 .img_id = self.id, 166 .options = p_opts, 167 }; 168 win.writeCell(0, 0, .{ .image = p }); 169} 170 171/// the size of the image, in cells 172pub fn cellSize(self: Image, win: Window) !CellSize { 173 // cell geometry 174 const x_pix = win.screen.width_pix; 175 const y_pix = win.screen.height_pix; 176 const w = win.screen.width; 177 const h = win.screen.height; 178 179 const pix_per_col = try std.math.divCeil(u16, x_pix, w); 180 const pix_per_row = try std.math.divCeil(u16, y_pix, h); 181 182 const cell_width = std.math.divCeil(u16, self.width, pix_per_col) catch 0; 183 const cell_height = std.math.divCeil(u16, self.height, pix_per_row) catch 0; 184 return .{ 185 .rows = cell_height, 186 .cols = cell_width, 187 }; 188}