Skip to content

Commit

Permalink
handle documentation generation
Browse files Browse the repository at this point in the history
Right now, in src/main.zig, GEN_DOCS must be manually set to true in order
to be able to run 'zig build docs'.
  • Loading branch information
zenith391 committed Feb 26, 2024
1 parent bde4d10 commit 584a5b4
Show file tree
Hide file tree
Showing 10 changed files with 318 additions and 295 deletions.
7 changes: 6 additions & 1 deletion build.zig
Original file line number Diff line number Diff line change
Expand Up @@ -83,11 +83,16 @@ pub fn build(b: *std.Build) !void {
.target = target,
.optimize = optimize,
});
// b.installDirectory(.{ .source_dir = docs.getEmittedDocs(), .install_dir = .{ .custom = "docs/" }, .install_subdir = "" });
const install_docs = b.addInstallDirectory(.{
.source_dir = docs.getEmittedDocs(),
.install_dir = .prefix,
.install_subdir = "docs",
});
const run_docs = try install(docs, .{ .link_libraries_on_root_module = true });

// DISABLED UNTIL ZIG DOESN'T CRASH WHILE GENERATING DOCS
const docs_step = b.step("docs", "Generate documentation and run unit tests");
docs_step.dependOn(&install_docs.step);
docs_step.dependOn(run_docs);

const coverage_tests = b.addTest(.{
Expand Down
6 changes: 6 additions & 0 deletions build_capy.zig
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ const Server = std.http.Server;

pub const CapyBuildOptions = struct {
app_name: []const u8 = "Capy Example",
windows: WindowsOptions = .{},
mac: MacOptions = .{},
linux: LinuxOptions = .{},
// TODO: disable android build if password is not set
// TODO: use optional
Expand All @@ -12,6 +14,10 @@ pub const CapyBuildOptions = struct {
args: ?[]const []const u8 = &.{},
link_libraries_on_root_module: bool = false,

pub const WindowsOptions = struct {};

pub const MacOptions = struct {};

pub const AndroidOptions = struct {
// As of 2022, 95% of Android devices use Android 8 (Oreo) or higher
version: AndroidSdk.AndroidVersion = .android8,
Expand Down
4 changes: 2 additions & 2 deletions src/audio.zig
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
//! Audio module with support for low-level and high-level
//! Audio module with an high-level and low-level interface
// TODO: move to an external package? if possible with WASM and Android?
const std = @import("std");
const internal = @import("internal.zig");
Expand All @@ -10,7 +10,7 @@ var generatorsMutex = std.Thread.Mutex{};

pub const AudioGenerator = struct {
write_callback: *const anyopaque, // due to a bug in zig compiler with false dependency loop
/// Time in frames. Note that, by desing, it overflows to 0 once the maximum is reached.
/// Time in frames. Note that, by design, it overflows to 0 once the maximum is reached.
time: u32 = 0,
channels: u16,
playing: bool = false,
Expand Down
3 changes: 1 addition & 2 deletions src/components/Button.zig
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,8 @@ const backend = @import("../backend.zig");
const internal = @import("../internal.zig");
const Size = @import("../data.zig").Size;
const Atom = @import("../data.zig").Atom;
const Container_Impl = @import("../containers.zig").Container_Impl;

/// A button component. Instantiated using `Button(.{ })`
/// A button component. Instantiated using `button(.{ })`
pub const Button = struct {
pub usingnamespace @import("../internal.zig").All(Button);

Expand Down
236 changes: 118 additions & 118 deletions src/components/Image.zig
Original file line number Diff line number Diff line change
Expand Up @@ -2,31 +2,31 @@ const std = @import("std");
const zigimg = @import("zigimg");
const backend = @import("../backend.zig");
const internal = @import("../internal.zig");
const Size = @import("../data.zig").Size;
const Atom = @import("../data.zig").Atom;
const assets = @import("../assets.zig");
// const Size = @import("../data.zig").Size;
// const Atom = @import("../data.zig").Atom;
// const assets = @import("../assets.zig");

// TODO: use zigimg's structs instead of duplicating efforts
const Colorspace = @import("../color.zig").Colorspace;
// const Colorspace = @import("../color.zig").Colorspace;

const ImageData = @import("../image.zig").ImageData;
const ScalableVectorData = @import("../image.zig").ScalableVectorData;
// const ImageData = @import("../image.zig").ImageData;
// const ScalableVectorData = @import("../image.zig").ScalableVectorData;

// TODO: convert to using a flat component so a backend may provide an Image backend
/// Component used to show an image.
pub const Image = struct {
pub usingnamespace @import("../internal.zig").All(Image);
// pub usingnamespace @import("../internal.zig").All(Image);

peer: ?backend.Canvas = null,
widget_data: Image.WidgetData = .{},
url: Atom([]const u8),
data: Atom(?ImageData) = Atom(?ImageData).of(null),
scaling: Atom(Scaling) = Atom(Scaling).of(.Fit),
// peer: ?backend.Canvas = null,
// widget_data: Image.WidgetData = .{},
// url: Atom([]const u8),
// data: Atom(?ImageData) = Atom(?ImageData).of(null),
// scaling: Atom(Scaling) = Atom(Scaling).of(.Fit),

// TODO: if vector graphics (SVG or TVG) then rerender every time Image component is resized
vectorData: Atom(?ScalableVectorData) = Atom(?ScalableVectorData).of(null),
// // TODO: if vector graphics (SVG or TVG) then rerender every time Image component is resized
// vectorData: Atom(?ScalableVectorData) = Atom(?ScalableVectorData).of(null),

// TODO: when url changes set data to null
// // TODO: when url changes set data to null

pub const Scaling = enum {
/// Keep the original size of the image
Expand All @@ -37,109 +37,109 @@ pub const Image = struct {
Stretch,
};

pub const DrawContext = backend.Canvas.DrawContext;

pub fn init(config: Image.Config) Image {
var self = Image.init_events(Image{ .url = Atom([]const u8).of(config.url) });
self.addDrawHandler(&Image.draw) catch unreachable;
@import("../internal.zig").applyConfigStruct(&self, config);
return self;
}

pub fn getPreferredSize(self: *Image, available: Size) Size {
if (self.data.get()) |data| {
return Size.init(data.width, data.height);
} else {
return Size.init(100, 30).intersect(available);
}
}

fn loadImage(self: *Image) !void {
// TODO: asynchronous loading
var handle = try assets.get(self.url.get());
defer handle.deinit();

var reader = handle.reader();
// TODO: progressive when I find a way to fit AssetHandle.Reader into zigimg
const contents = try reader.readAllAlloc(internal.scratch_allocator, std.math.maxInt(usize));
defer internal.scratch_allocator.free(contents);

const data = try ImageData.fromBuffer(internal.lasting_allocator, contents);
self.data.set(data);
}

pub fn draw(self: *Image, ctx: *DrawContext) !void {
const width = self.getWidth();
const height = self.getHeight();

if (self.data.get() == null) {
self.loadImage() catch |err| {
std.log.err("{s}", .{@errorName(err)});
if (@errorReturnTrace()) |trace| {
std.debug.dumpStackTrace(trace.*);
}
};

// TODO: render a placeholder
return;
}

const img = self.data.get().?;
switch (self.scaling.get()) {
.None => {
const imgX = @as(i32, @intCast(width / 2)) - @as(i32, @intCast(img.width / 2));
const imgY = @as(i32, @intCast(height / 2)) - @as(i32, @intCast(img.height / 2));
ctx.image(
imgX,
imgY,
img.width,
img.height,
img,
);
},
.Fit => {
// The aspect ratio of the img
const ratio = @as(f32, @floatFromInt(img.width)) / @as(f32, @floatFromInt(img.height));
var imgW: u32 = undefined;
var imgH: u32 = undefined;

if (@as(f32, @floatFromInt(width)) / ratio < @as(f32, @floatFromInt(height))) {
imgW = width;
imgH = @as(u32, @intFromFloat(@as(f32, @floatFromInt(imgW)) / ratio));
} else {
imgH = height;
imgW = @as(u32, @intFromFloat(@as(f32, @floatFromInt(imgH)) * ratio));
}

const imgX = @as(i32, @intCast(width / 2)) - @as(i32, @intCast(imgW / 2));
const imgY = @as(i32, @intCast(height / 2)) - @as(i32, @intCast(imgH / 2));

ctx.image(
imgX,
imgY,
imgW,
imgH,
img,
);
},
.Stretch => {
ctx.image(
0,
0,
img.width,
img.height,
img,
);
},
}
}

pub fn show(self: *Image) !void {
if (self.peer == null) {
self.peer = try backend.Canvas.create();
try self.setupEvents();
}
}
// pub const DrawContext = backend.Canvas.DrawContext;

// pub fn init(config: Image.Config) Image {
// var self = Image.init_events(Image{ .url = Atom([]const u8).of(config.url) });
// self.addDrawHandler(&Image.draw) catch unreachable;
// @import("../internal.zig").applyConfigStruct(&self, config);
// return self;
// }

// pub fn getPreferredSize(self: *Image, available: Size) Size {
// if (self.data.get()) |data| {
// return Size.init(data.width, data.height);
// } else {
// return Size.init(100, 30).intersect(available);
// }
// }

// fn loadImage(self: *Image) !void {
// // TODO: asynchronous loading
// var handle = try assets.get(self.url.get());
// defer handle.deinit();

// var reader = handle.reader();
// // TODO: progressive when I find a way to fit AssetHandle.Reader into zigimg
// const contents = try reader.readAllAlloc(internal.scratch_allocator, std.math.maxInt(usize));
// defer internal.scratch_allocator.free(contents);

// const data = try ImageData.fromBuffer(internal.lasting_allocator, contents);
// self.data.set(data);
// }

// pub fn draw(self: *Image, ctx: *DrawContext) !void {
// const width = self.getWidth();
// const height = self.getHeight();

// if (self.data.get() == null) {
// self.loadImage() catch |err| {
// std.log.err("{s}", .{@errorName(err)});
// if (@errorReturnTrace()) |trace| {
// std.debug.dumpStackTrace(trace.*);
// }
// };

// // TODO: render a placeholder
// return;
// }

// const img = self.data.get().?;
// switch (self.scaling.get()) {
// .None => {
// const imgX = @as(i32, @intCast(width / 2)) - @as(i32, @intCast(img.width / 2));
// const imgY = @as(i32, @intCast(height / 2)) - @as(i32, @intCast(img.height / 2));
// ctx.image(
// imgX,
// imgY,
// img.width,
// img.height,
// img,
// );
// },
// .Fit => {
// // The aspect ratio of the img
// const ratio = @as(f32, @floatFromInt(img.width)) / @as(f32, @floatFromInt(img.height));
// var imgW: u32 = undefined;
// var imgH: u32 = undefined;

// if (@as(f32, @floatFromInt(width)) / ratio < @as(f32, @floatFromInt(height))) {
// imgW = width;
// imgH = @as(u32, @intFromFloat(@as(f32, @floatFromInt(imgW)) / ratio));
// } else {
// imgH = height;
// imgW = @as(u32, @intFromFloat(@as(f32, @floatFromInt(imgH)) * ratio));
// }

// const imgX = @as(i32, @intCast(width / 2)) - @as(i32, @intCast(imgW / 2));
// const imgY = @as(i32, @intCast(height / 2)) - @as(i32, @intCast(imgH / 2));

// ctx.image(
// imgX,
// imgY,
// imgW,
// imgH,
// img,
// );
// },
// .Stretch => {
// ctx.image(
// 0,
// 0,
// img.width,
// img.height,
// img,
// );
// },
// }
// }

// pub fn show(self: *Image) !void {
// if (self.peer == null) {
// self.peer = try backend.Canvas.create();
// try self.setupEvents();
// }
// }
};

pub fn image(config: Image.Config) *Image {
Expand Down
2 changes: 1 addition & 1 deletion src/data.zig
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ pub const Easings = struct {
}
};

pub fn Animation(comptime T: type) type {
fn Animation(comptime T: type) type {
return struct {
start: i64,
/// Assume animation won't last more than 4000000 seconds
Expand Down
3 changes: 2 additions & 1 deletion src/http.zig
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
//! Module to handle HTTP(S) requests
//! This is useful as it is a very common operation that's not done the same on every devices
//!
//! The module was created because it is a very common operation that's not done the same on every devices
//! (For example, on the Web, you can't make TCP sockets, so std.http won't work)
const std = @import("std");
const internal = @import("internal.zig");
Expand Down
Loading

0 comments on commit 584a5b4

Please sign in to comment.