diff --git a/conformance/blocks.zig b/conformance/blocks.zig index 288d1ffb7..a92f73893 100644 --- a/conformance/blocks.zig +++ b/conformance/blocks.zig @@ -64,4 +64,43 @@ pub fn main() !void { try stdout.print("\n\n", .{}); } } + + { + try stdout.print("\x1b[4mWedge Triangles\x1b[0m\n", .{}); + { + var i: usize = 0x1FB3C; + const end = 0x1FB40; + while (i <= end) : (i += 1) { + try stdout.print("{u} ", .{@intCast(u21, i)}); + } + } + { + var i: usize = 0x1FB47; + const end = 0x1FB4B; + while (i <= end) : (i += 1) { + try stdout.print("{u} ", .{@intCast(u21, i)}); + } + } + { + var i: usize = 0x1FB57; + const end = 0x1FB5B; + while (i <= end) : (i += 1) { + try stdout.print("{u} ", .{@intCast(u21, i)}); + } + } + { + var i: usize = 0x1FB62; + const end = 0x1FB66; + while (i <= end) : (i += 1) { + try stdout.print("{u} ", .{@intCast(u21, i)}); + } + } + { + var i: usize = 0x1FB6C; + const end = 0x1FB6F; + while (i <= end) : (i += 1) { + try stdout.print("{u} ", .{@intCast(u21, i)}); + } + } + } } diff --git a/pkg/pixman/image.zig b/pkg/pixman/image.zig index 22c55c7ac..b285744cd 100644 --- a/pkg/pixman/image.zig +++ b/pkg/pixman/image.zig @@ -19,6 +19,14 @@ pub const Image = opaque { )) orelse return pixman.Error.PixmanFailure; } + pub fn createSolidFill( + color: pixman.Color, + ) pixman.Error!*Image { + return @ptrCast(?*Image, c.pixman_image_create_solid_fill( + @ptrCast(*const c.pixman_color_t, &color), + )) orelse return pixman.Error.PixmanFailure; + } + pub fn unref(self: *Image) bool { return c.pixman_image_unref(@ptrCast(*c.pixman_image_t, self)) == 1; } @@ -90,6 +98,31 @@ pub const Image = opaque { y_off, ); } + + pub fn compositeTriangles( + self: *Image, + op: pixman.Op, + src: *Image, + mask_format: pixman.FormatCode, + x_src: c_int, + y_src: c_int, + x_dst: c_int, + y_dst: c_int, + tris: []const pixman.Triangle, + ) void { + c.pixman_composite_triangles( + @enumToInt(op), + @ptrCast(*c.pixman_image_t, src), + @ptrCast(*c.pixman_image_t, self), + @enumToInt(mask_format), + x_src, + y_src, + x_dst, + y_dst, + @intCast(c_int, tris.len), + @ptrCast([*c]const c.pixman_triangle_t, tris.ptr), + ); + } }; test "create and destroy" { diff --git a/pkg/pixman/types.zig b/pkg/pixman/types.zig index acebba68e..f1ab9235d 100644 --- a/pkg/pixman/types.zig +++ b/pkg/pixman/types.zig @@ -93,6 +93,12 @@ pub const LineFixed = extern struct { p2: PointFixed, }; +pub const Triangle = extern struct { + p1: PointFixed, + p2: PointFixed, + p3: PointFixed, +}; + pub const Trapezoid = extern struct { top: Fixed, bottom: Fixed, diff --git a/src/font/BoxFont.zig b/src/font/BoxFont.zig index 3d2668ddc..94977fbbe 100644 --- a/src/font/BoxFont.zig +++ b/src/font/BoxFont.zig @@ -302,6 +302,13 @@ fn draw(self: BoxFont, alloc: Allocator, img: *pixman.Image, cp: u32) !void { 0x1FB00...0x1FB3B => self.draw_sextant(img, cp), + 0x1fb3c...0x1fb40, + 0x1fb47...0x1fb4b, + 0x1fb57...0x1fb5b, + 0x1fb62...0x1fb66, + 0x1fb6c...0x1fb6f, + => try self.draw_wedge_triangle(img, cp), + else => return error.InvalidCodepoint, } } @@ -1658,17 +1665,8 @@ fn draw_sextant(self: BoxFont, img: *pixman.Image, cp: u32) void { const idx = cp - 0x1fb00; const encoded = matrix[idx]; - const x_halfs: [2]u32 = .{ - @floatToInt(u32, @round(@intToFloat(f64, self.width) / 2)), - @floatToInt(u32, @intToFloat(f64, self.width) / 2), - }; - - const y_thirds: [2]u32 = switch (@mod(self.height, 3)) { - 0 => .{ self.height / 3, 2 * self.height / 3 }, - 1 => .{ self.height / 3, 2 * self.height / 3 + 1 }, - 2 => .{ self.height / 3 + 1, 2 * self.height / 3 }, - else => unreachable, - }; + const x_halfs = self.xHalfs(); + const y_thirds = self.yThirds(); if (encoded & UPPER_LEFT > 0) self.rect(img, 0, 0, x_halfs[0], y_thirds[0]); if (encoded & MIDDLE_LEFT > 0) self.rect(img, 0, y_thirds[0], x_halfs[0], y_thirds[1]); @@ -1678,6 +1676,381 @@ fn draw_sextant(self: BoxFont, img: *pixman.Image, cp: u32) void { if (encoded & LOWER_RIGHT > 0) self.rect(img, x_halfs[1], y_thirds[1], self.width, self.height); } +fn xHalfs(self: BoxFont) [2]u32 { + return .{ + @floatToInt(u32, @round(@intToFloat(f64, self.width) / 2)), + @floatToInt(u32, @intToFloat(f64, self.width) / 2), + }; +} + +fn yThirds(self: BoxFont) [2]u32 { + return switch (@mod(self.height, 3)) { + 0 => .{ self.height / 3, 2 * self.height / 3 }, + 1 => .{ self.height / 3, 2 * self.height / 3 + 1 }, + 2 => .{ self.height / 3 + 1, 2 * self.height / 3 }, + else => unreachable, + }; +} + +fn draw_wedge_triangle(self: BoxFont, img: *pixman.Image, cp: u32) !void { + const width = self.width; + const height = self.height; + + const x_halfs = self.xHalfs(); + const y_thirds = self.yThirds(); + const halfs0 = x_halfs[0]; + const halfs1 = x_halfs[1]; + const thirds0 = y_thirds[0]; + const thirds1 = y_thirds[1]; + + var p1_x: u32 = 0; + var p2_x: u32 = 0; + var p3_x: u32 = 0; + var p1_y: u32 = 0; + var p2_y: u32 = 0; + var p3_y: u32 = 0; + + switch (cp) { + 0x1fb3c => { + p3_x = halfs0; + p1_y = thirds1; + p2_y = height; + p3_y = height; + }, + + 0x1fb52 => { + p3_x = halfs0; + p1_y = thirds1; + p2_y = height; + p3_y = height; + }, + + 0x1fb3d => { + p3_x = width; + p1_y = thirds1; + p2_y = height; + p3_y = height; + }, + + 0x1fb53 => { + p3_x = width; + p1_y = thirds1; + p2_y = height; + p3_y = height; + }, + + 0x1fb3e => { + p3_x = halfs0; + p1_y = thirds0; + p2_y = height; + p3_y = height; + }, + + 0x1fb54 => { + p3_x = halfs0; + p1_y = thirds0; + p2_y = height; + p3_y = height; + }, + + 0x1fb3f => { + p3_x = width; + p1_y = thirds0; + p2_y = height; + p3_y = height; + }, + + 0x1fb55 => { + p3_x = width; + p1_y = thirds0; + p2_y = height; + p3_y = height; + }, + + 0x1fb40, 0x1fb56 => { + p3_x = halfs0; + p1_y = 0; + p2_y = height; + p3_y = height; + }, + + 0x1fb47 => { + p1_x = width; + p2_x = width; + p3_x = halfs1; + p1_y = thirds1; + p2_y = height; + p3_y = height; + }, + + 0x1fb5d => { + p1_x = width; + p2_x = width; + p3_x = halfs1; + p1_y = thirds1; + p2_y = height; + p3_y = height; + }, + + 0x1fb48 => { + p1_x = width; + p2_x = width; + p3_x = 0; + p1_y = thirds1; + p2_y = height; + p3_y = height; + }, + + 0x1fb5e => { + p1_x = width; + p2_x = width; + p3_x = 0; + p1_y = thirds1; + p2_y = height; + p3_y = height; + }, + + 0x1fb49 => { + p1_x = width; + p2_x = width; + p3_x = halfs1; + p1_y = thirds0; + p2_y = height; + p3_y = height; + }, + + 0x1fb5f => { + p1_x = width; + p2_x = width; + p3_x = halfs1; + p1_y = thirds0; + p2_y = height; + p3_y = height; + }, + + 0x1fb4a => { + p1_x = width; + p2_x = width; + p3_x = 0; + p1_y = thirds0; + p2_y = height; + p3_y = height; + }, + + 0x1fb60 => { + p1_x = width; + p2_x = width; + p3_x = 0; + p1_y = thirds0; + p2_y = height; + p3_y = height; + }, + + 0x1fb4b, 0x1fb61 => { + p1_x = width; + p2_x = width; + p3_x = halfs1; + p1_y = 0; + p2_y = height; + p3_y = height; + }, + + 0x1fb57 => { + p3_x = halfs0; + p2_y = thirds0; + }, + + 0x1fb41 => { + p3_x = halfs0; + p2_y = thirds0; + }, + + 0x1fb58 => { + p3_x = width; + p2_y = thirds0; + }, + + 0x1fb42 => { + p3_x = width; + p2_y = thirds0; + }, + + 0x1fb59 => { + p3_x = halfs0; + p2_y = thirds1; + }, + + 0x1fb43 => { + p3_x = halfs0; + p2_y = thirds1; + }, + + 0x1fb5a => { + p3_x = width; + p2_y = thirds1; + }, + + 0x1fb44 => { + p3_x = width; + p2_y = thirds1; + }, + + 0x1fb5b, 0x1fb45 => { + p3_x = halfs0; + p2_y = height; + }, + + 0x1fb62 => { + p1_x = width; + p2_x = width; + p3_x = halfs1; + p2_y = thirds0; + }, + + 0x1fb4c => { + p1_x = width; + p2_x = width; + p3_x = halfs1; + p2_y = thirds0; + }, + + 0x1fb63 => { + p1_x = width; + p2_x = width; + p3_x = 0; + p2_y = thirds0; + }, + + 0x1fb4d => { + p1_x = width; + p2_x = width; + p3_x = 0; + p2_y = thirds0; + }, + + 0x1fb64 => { + p1_x = width; + p2_x = width; + p3_x = halfs1; + p2_y = thirds1; + }, + + 0x1fb4e => { + p1_x = width; + p2_x = width; + p3_x = halfs1; + p2_y = thirds1; + }, + + 0x1fb65 => { + p1_x = width; + p2_x = width; + p3_x = 0; + p2_y = thirds1; + }, + + 0x1fb4f => { + p1_x = width; + p2_x = width; + p3_x = 0; + p2_y = thirds1; + }, + + 0x1fb66, 0x1fb50 => { + p1_x = width; + p2_x = width; + p3_x = halfs1; + p2_y = height; + }, + + 0x1fb46 => { + p1_x = 0; + p1_y = thirds1; + p2_x = width; + p2_y = thirds0; + p3_x = width; + p3_y = p1_y; + }, + + 0x1fb51 => { + p1_x = 0; + p1_y = thirds0; + p2_x = 0; + p2_y = thirds1; + p3_x = width; + p3_y = p2_y; + }, + + 0x1fb5c => { + p1_x = 0; + p1_y = thirds0; + p2_x = 0; + p2_y = thirds1; + p3_x = width; + p3_y = p1_y; + }, + + 0x1fb67 => { + p1_x = 0; + p1_y = thirds0; + p2_x = width; + p2_y = p1_y; + p3_x = width; + p3_y = thirds1; + }, + + 0x1fb6c, 0x1fb68 => { + p1_x = 0; + p1_y = 0; + p2_x = halfs0; + p2_y = height / 2; + p3_x = 0; + p3_y = height; + }, + + 0x1fb6d, 0x1fb69 => { + p1_x = 0; + p1_y = 0; + p2_x = halfs1; + p2_y = height / 2; + p3_x = width; + p3_y = 0; + }, + + 0x1fb6e, 0x1fb6a => { + p1_x = width; + p1_y = 0; + p2_x = halfs1; + p2_y = height / 2; + p3_x = width; + p3_y = height; + }, + + 0x1fb6f, 0x1fb6b => { + p1_x = 0; + p1_y = height; + p2_x = halfs1; + p2_y = height / 2; + p3_x = width; + p3_y = height; + }, + + else => unreachable, + } + + const tris = &[_]pixman.Triangle{ + .{ + .p1 = .{ .x = pixman.Fixed.init(p1_x), .y = pixman.Fixed.init(p1_y) }, + .p2 = .{ .x = pixman.Fixed.init(p2_x), .y = pixman.Fixed.init(p2_y) }, + .p3 = .{ .x = pixman.Fixed.init(p3_x), .y = pixman.Fixed.init(p3_y) }, + }, + }; + + const src = try pixman.Image.createSolidFill(white); + defer _ = src.unref(); + img.compositeTriangles(.over, src, .a8, 0, 0, 0, 0, tris); +} + fn draw_light_arc( self: BoxFont, alloc: Allocator, diff --git a/src/font/Group.zig b/src/font/Group.zig index 60d372c9e..0746765e9 100644 --- a/src/font/Group.zig +++ b/src/font/Group.zig @@ -194,6 +194,12 @@ pub fn indexForCodepoint( // "Symbols for Legacy Computing" block 0x1FB00...0x1FB3B => true, + 0x1FB3C...0x1FB40, + 0x1FB47...0x1FB4B, + 0x1FB57...0x1FB5B, + 0x1FB62...0x1FB66, + 0x1FB6C...0x1FB6F, + => true, else => false, }) {