diff --git a/src/font/sprite/draw/block.zig b/src/font/sprite/draw/block.zig index f7faacea7..571f25a79 100644 --- a/src/font/sprite/draw/block.zig +++ b/src/font/sprite/draw/block.zig @@ -15,9 +15,7 @@ const common = @import("common.zig"); const Shade = common.Shade; const Quads = common.Quads; const Alignment = common.Alignment; -const xHalfs = common.xHalfs; -const yHalfs = common.yHalfs; -const rect = common.rect; +const fill = common.fill; const font = @import("../../main.zig"); const Sprite = @import("../../sprite.zig").Sprite; @@ -176,11 +174,8 @@ fn quadrant( canvas: *font.sprite.Canvas, comptime quads: Quads, ) void { - const x_halfs = xHalfs(metrics); - const y_halfs = yHalfs(metrics); - - if (quads.tl) rect(metrics, canvas, 0, 0, x_halfs[0], y_halfs[0]); - if (quads.tr) rect(metrics, canvas, x_halfs[1], 0, metrics.cell_width, y_halfs[0]); - if (quads.bl) rect(metrics, canvas, 0, y_halfs[1], x_halfs[0], metrics.cell_height); - if (quads.br) rect(metrics, canvas, x_halfs[1], y_halfs[1], metrics.cell_width, metrics.cell_height); + if (quads.tl) fill(metrics, canvas, .zero, .half, .zero, .half); + if (quads.tr) fill(metrics, canvas, .half, .full, .zero, .half); + if (quads.bl) fill(metrics, canvas, .zero, .half, .half, .full); + if (quads.br) fill(metrics, canvas, .half, .full, .half, .full); } diff --git a/src/font/sprite/draw/box.zig b/src/font/sprite/draw/box.zig index 91d78d2b2..f14e5a3f9 100644 --- a/src/font/sprite/draw/box.zig +++ b/src/font/sprite/draw/box.zig @@ -24,7 +24,6 @@ const Quads = common.Quads; const Corner = common.Corner; const Edge = common.Edge; const Alignment = common.Alignment; -const rect = common.rect; const hline = common.hline; const vline = common.vline; const hlineMiddle = common.hlineMiddle; @@ -695,20 +694,6 @@ pub fn lightDiagonalCross( lightDiagonalUpperLeftToLowerRight(metrics, canvas); } -fn quadrant( - metrics: font.Metrics, - canvas: *font.sprite.Canvas, - comptime quads: Quads, -) void { - const center_x = metrics.cell_width / 2 + metrics.cell_width % 2; - const center_y = metrics.cell_height / 2 + metrics.cell_height % 2; - - if (quads.tl) rect(metrics, canvas, 0, 0, center_x, center_y); - if (quads.tr) rect(metrics, canvas, center_x, 0, metrics.cell_width, center_y); - if (quads.bl) rect(metrics, canvas, 0, center_y, center_x, metrics.cell_height); - if (quads.br) rect(metrics, canvas, center_x, center_y, metrics.cell_width, metrics.cell_height); -} - pub fn arc( metrics: font.Metrics, canvas: *font.sprite.Canvas, diff --git a/src/font/sprite/draw/common.zig b/src/font/sprite/draw/common.zig index d10128cdf..67b9dc778 100644 --- a/src/font/sprite/draw/common.zig +++ b/src/font/sprite/draw/common.zig @@ -122,22 +122,203 @@ pub const Alignment = struct { pub const bottom_right = lower_right; }; -/// Fill a rect, clamped to within the cell boundaries. +/// A value that indicates some fraction across +/// the cell either horizontally or vertically. /// -/// TODO: Eliminate usages of this, prefer `canvas.box`. -pub fn rect( +/// This has some redundant names in it so that you can +/// use whichever one feels most semantically appropriate. +pub const Fraction = enum { + // Names for the min edge + start, + left, + top, + zero, + + // Names based on eighths + eighth, + one_eighth, + two_eighths, + three_eighths, + four_eighths, + five_eighths, + six_eighths, + seven_eighths, + + // Names based on quarters + quarter, + one_quarter, + two_quarters, + three_quarters, + + // Names based on thirds + third, + one_third, + two_thirds, + + // Names based on halves + half, + one_half, + + // Alternative names for 1/2 + center, + middle, + + // Names for the max edge + end, + right, + bottom, + one, + full, + + /// This can be indexed to get the fraction for `i/8`. + pub const eighths: [9]Fraction = .{ + .zero, + .one_eighth, + .two_eighths, + .three_eighths, + .four_eighths, + .five_eighths, + .six_eighths, + .seven_eighths, + .one, + }; + + /// This can be indexed to get the fraction for `i/4`. + pub const quarters: [5]Fraction = .{ + .zero, + .one_quarter, + .two_quarters, + .three_quarters, + .one, + }; + + /// This can be indexed to get the fraction for `i/3`. + pub const thirds: [4]Fraction = .{ + .zero, + .one_third, + .two_thirds, + .one, + }; + + /// This can be indexed to get the fraction for `i/2`. + pub const halves: [3]Fraction = .{ + .zero, + .one_half, + .one, + }; + + /// Get the x position for this fraction across a particular + /// size (width or height), assuming it will be used as the + /// min (left/top) coordinate for a block. + /// + /// `size` can be any integer type, since it will be coerced + pub inline fn min(self: Fraction, size: anytype) i32 { + const s: f64 = @as(f64, @floatFromInt(size)); + // For min coordinates, we want to align with the complementary + // fraction taken from the end, this ensures that rounding evens + // out, so that for example, if `size` is `7`, and we're looking + // at the `half` line, `size - round((1 - 0.5) * size)` => `3`; + // whereas the max coordinate directly rounds, which means that + // both `start` -> `half` and `half` -> `end` will be 4px, from + // `0` -> `4` and `3` -> `7`. + return @intFromFloat(s - @round((1.0 - self.fraction()) * s)); + } + + /// Get the x position for this fraction across a particular + /// size (width or height), assuming it will be used as the + /// max (right/bottom) coordinate for a block. + /// + /// `size` can be any integer type, since it will be coerced + /// with `@floatFromInt`. + pub inline fn max(self: Fraction, size: anytype) i32 { + const s: f64 = @as(f64, @floatFromInt(size)); + // See explanation of why these are different in `min`. + return @intFromFloat(@round(self.fraction() * s)); + } + + /// Get this fraction across a particular size (width/height). + /// If you need an integer, use `min` or `max` instead, since + /// they contain special logic for consistent alignment. This + /// is for when you're drawing with paths and don't care about + /// pixel alignment. + /// + /// `size` can be any integer type, since it will be coerced + /// with `@floatFromInt`. + pub inline fn float(self: Fraction, size: anytype) f64 { + return self.fraction() * @as(f64, @floatFromInt(size)); + } + + /// Get a float for the fraction this represents. + pub inline fn fraction(self: Fraction) f64 { + return switch (self) { + .start, + .left, + .top, + .zero, + => 0.0, + + .eighth, + .one_eighth, + => 0.125, + + .quarter, + .one_quarter, + .two_eighths, + => 0.25, + + .third, + .one_third, + => 1.0 / 3.0, + + .three_eighths, + => 0.375, + + .half, + .one_half, + .two_quarters, + .four_eighths, + .center, + .middle, + => 0.5, + + .five_eighths, + => 0.625, + + .two_thirds, + => 2.0 / 3.0, + + .three_quarters, + .six_eighths, + => 0.75, + + .seven_eighths, + => 0.875, + + .end, + .right, + .bottom, + .one, + .full, + => 1.0, + }; + } +}; + +/// Fill a section of the cell, specified by a +/// horizontal and vertical pair of fraction lines. +pub fn fill( metrics: font.Metrics, canvas: *font.sprite.Canvas, - x1: u32, - y1: u32, - x2: u32, - y2: u32, + x0: Fraction, + x1: Fraction, + y0: Fraction, + y1: Fraction, ) void { canvas.box( - @intCast(@min(@max(x1, 0), metrics.cell_width)), - @intCast(@min(@max(y1, 0), metrics.cell_height)), - @intCast(@min(@max(x2, 0), metrics.cell_width)), - @intCast(@min(@max(y2, 0), metrics.cell_height)), + x0.min(metrics.cell_width), + y0.min(metrics.cell_height), + x1.max(metrics.cell_width), + y1.max(metrics.cell_height), .on, ); } @@ -195,58 +376,3 @@ pub fn hline( ) void { canvas.box(x1, y, x2, y + @as(i32, @intCast(thickness_px)), .on); } - -/// xHalfs[0] should be used as the right edge of a left-aligned half. -/// xHalfs[1] should be used as the left edge of a right-aligned half. -pub fn xHalfs(metrics: font.Metrics) [2]u32 { - const float_width: f64 = @floatFromInt(metrics.cell_width); - const half_width: u32 = @intFromFloat(@round(0.5 * float_width)); - return .{ half_width, metrics.cell_width - half_width }; -} - -/// yHalfs[0] should be used as the bottom edge of a top-aligned half. -/// yHalfs[1] should be used as the top edge of a bottom-aligned half. -pub fn yHalfs(metrics: font.Metrics) [2]u32 { - const float_height: f64 = @floatFromInt(metrics.cell_height); - const half_height: u32 = @intFromFloat(@round(0.5 * float_height)); - return .{ half_height, metrics.cell_height - half_height }; -} - -/// Use these values as such: -/// yThirds[0] bottom edge of the first third. -/// yThirds[1] top edge of the second third. -/// yThirds[2] bottom edge of the second third. -/// yThirds[3] top edge of the final third. -pub fn yThirds(metrics: font.Metrics) [4]u32 { - const float_height: f64 = @floatFromInt(metrics.cell_height); - const one_third_height: u32 = @intFromFloat(@round(one_third * float_height)); - const two_thirds_height: u32 = @intFromFloat(@round(two_thirds * float_height)); - return .{ - one_third_height, - metrics.cell_height - two_thirds_height, - two_thirds_height, - metrics.cell_height - one_third_height, - }; -} - -/// Use these values as such: -/// yQuads[0] bottom edge of first quarter. -/// yQuads[1] top edge of second quarter. -/// yQuads[2] bottom edge of second quarter. -/// yQuads[3] top edge of third quarter. -/// yQuads[4] bottom edge of third quarter -/// yQuads[5] top edge of fourth quarter. -pub fn yQuads(metrics: font.Metrics) [6]u32 { - const float_height: f64 = @floatFromInt(metrics.cell_height); - const quarter_height: u32 = @intFromFloat(@round(0.25 * float_height)); - const half_height: u32 = @intFromFloat(@round(0.50 * float_height)); - const three_quarters_height: u32 = @intFromFloat(@round(0.75 * float_height)); - return .{ - quarter_height, - metrics.cell_height - three_quarters_height, - half_height, - metrics.cell_height - half_height, - three_quarters_height, - metrics.cell_height - quarter_height, - }; -} diff --git a/src/font/sprite/draw/symbols_for_legacy_computing.zig b/src/font/sprite/draw/symbols_for_legacy_computing.zig index a17ddb494..164aa1ac3 100644 --- a/src/font/sprite/draw/symbols_for_legacy_computing.zig +++ b/src/font/sprite/draw/symbols_for_legacy_computing.zig @@ -28,13 +28,12 @@ const z2d = @import("z2d"); const common = @import("common.zig"); const Thickness = common.Thickness; const Alignment = common.Alignment; +const Fraction = common.Fraction; const Corner = common.Corner; const Quads = common.Quads; const Edge = common.Edge; const Shade = common.Shade; -const xHalfs = common.xHalfs; -const yThirds = common.yThirds; -const rect = common.rect; +const fill = common.fill; const box = @import("box.zig"); const block = @import("block.zig"); @@ -121,16 +120,12 @@ pub fn draw1FB00_1FB3B( const sex: Sextants = @bitCast(@as(u6, @intCast( idx + (idx / 0x14) + 1, ))); - - const x_halfs = xHalfs(metrics); - const y_thirds = yThirds(metrics); - - if (sex.tl) rect(metrics, canvas, 0, 0, x_halfs[0], y_thirds[0]); - if (sex.tr) rect(metrics, canvas, x_halfs[1], 0, metrics.cell_width, y_thirds[0]); - if (sex.ml) rect(metrics, canvas, 0, y_thirds[1], x_halfs[0], y_thirds[2]); - if (sex.mr) rect(metrics, canvas, x_halfs[1], y_thirds[1], metrics.cell_width, y_thirds[2]); - if (sex.bl) rect(metrics, canvas, 0, y_thirds[3], x_halfs[0], metrics.cell_height); - if (sex.br) rect(metrics, canvas, x_halfs[1], y_thirds[3], metrics.cell_width, metrics.cell_height); + if (sex.tl) fill(metrics, canvas, .zero, .half, .zero, .one_third); + if (sex.tr) fill(metrics, canvas, .half, .full, .zero, .one_third); + if (sex.ml) fill(metrics, canvas, .zero, .half, .one_third, .two_thirds); + if (sex.mr) fill(metrics, canvas, .half, .full, .one_third, .two_thirds); + if (sex.bl) fill(metrics, canvas, .zero, .half, .two_thirds, .end); + if (sex.br) fill(metrics, canvas, .half, .full, .two_thirds, .end); } /// Smooth Mosaics @@ -465,17 +460,12 @@ pub fn draw1FB3C_1FB67( else => unreachable, }; - const y_thirds = yThirds(metrics); const top: f64 = 0.0; - // We average the edge positions for the y_thirds boundaries here - // rather than having to deal with varying alignments depending on - // the surrounding pieces. The most this will be off by is half of - // a pixel, so hopefully it's not noticeable. - const upper: f64 = 0.5 * (@as(f64, @floatFromInt(y_thirds[0])) + @as(f64, @floatFromInt(y_thirds[1]))); - const lower: f64 = 0.5 * (@as(f64, @floatFromInt(y_thirds[2])) + @as(f64, @floatFromInt(y_thirds[3]))); + const upper: f64 = Fraction.one_third.float(metrics.cell_height); + const lower: f64 = Fraction.two_thirds.float(metrics.cell_height); const bottom: f64 = @floatFromInt(metrics.cell_height); const left: f64 = 0.0; - const center: f64 = @round(@as(f64, @floatFromInt(metrics.cell_width)) / 2); + const center: f64 = Fraction.half.float(metrics.cell_width); const right: f64 = @floatFromInt(metrics.cell_width); var path = canvas.staticPath(12); // nodes.len = 0 @@ -571,13 +561,14 @@ pub fn draw1FB70_1FB75( const n = cp + 1 - 0x1fb70; - const x: u32 = @intFromFloat( - @round(@as(f64, @floatFromInt(n)) * @as(f64, @floatFromInt(metrics.cell_width)) / 8), + fill( + metrics, + canvas, + Fraction.eighths[n], + Fraction.eighths[n + 1], + .top, + .bottom, ); - const w: u32 = @intFromFloat( - @round(@as(f64, @floatFromInt(metrics.cell_width)) / 8), - ); - rect(metrics, canvas, x, 0, x + w, metrics.cell_height); } /// Horizontal one eighth blocks @@ -593,21 +584,14 @@ pub fn draw1FB76_1FB7B( const n = cp + 1 - 0x1fb76; - const h = @as( - u32, - @intFromFloat(@round(@as(f64, @floatFromInt(metrics.cell_height)) / 8)), + fill( + metrics, + canvas, + .left, + .right, + Fraction.eighths[n], + Fraction.eighths[n + 1], ); - const y = @min( - metrics.cell_height -| h, - @as( - u32, - @intFromFloat( - @round(@as(f64, @floatFromInt(n)) * - @as(f64, @floatFromInt(metrics.cell_height)) / 8), - ), - ), - ); - rect(metrics, canvas, 0, y, metrics.cell_width, y + h); } pub fn draw1FB7C_1FB97( @@ -1383,7 +1367,7 @@ fn checkerboardFill( } } -fn circle( +pub fn circle( metrics: font.Metrics, canvas: *font.sprite.Canvas, comptime position: Alignment, diff --git a/src/font/sprite/draw/symbols_for_legacy_computing_supplement.zig b/src/font/sprite/draw/symbols_for_legacy_computing_supplement.zig index 9ae92cc72..f43949eb9 100644 --- a/src/font/sprite/draw/symbols_for_legacy_computing_supplement.zig +++ b/src/font/sprite/draw/symbols_for_legacy_computing_supplement.zig @@ -55,13 +55,13 @@ const z2d = @import("z2d"); const common = @import("common.zig"); const Thickness = common.Thickness; +const Fraction = common.Fraction; const Corner = common.Corner; const Shade = common.Shade; -const xHalfs = common.xHalfs; -const yQuads = common.yQuads; -const rect = common.rect; +const fill = common.fill; const box = @import("box.zig"); +const sflc = @import("symbols_for_legacy_computing.zig"); const font = @import("../../main.zig"); @@ -122,17 +122,15 @@ pub fn draw1CD00_1CDE5( break :octants result; }; - const x_halfs = xHalfs(metrics); - const y_quads = yQuads(metrics); const oct = octants[cp - octant_min]; - if (oct.@"1") rect(metrics, canvas, 0, 0, x_halfs[0], y_quads[0]); - if (oct.@"2") rect(metrics, canvas, x_halfs[1], 0, metrics.cell_width, y_quads[0]); - if (oct.@"3") rect(metrics, canvas, 0, y_quads[1], x_halfs[0], y_quads[2]); - if (oct.@"4") rect(metrics, canvas, x_halfs[1], y_quads[1], metrics.cell_width, y_quads[2]); - if (oct.@"5") rect(metrics, canvas, 0, y_quads[3], x_halfs[0], y_quads[4]); - if (oct.@"6") rect(metrics, canvas, x_halfs[1], y_quads[3], metrics.cell_width, y_quads[4]); - if (oct.@"7") rect(metrics, canvas, 0, y_quads[5], x_halfs[0], metrics.cell_height); - if (oct.@"8") rect(metrics, canvas, x_halfs[1], y_quads[5], metrics.cell_width, metrics.cell_height); + if (oct.@"1") fill(metrics, canvas, .zero, .half, .zero, .one_quarter); + if (oct.@"2") fill(metrics, canvas, .half, .full, .zero, .one_quarter); + if (oct.@"3") fill(metrics, canvas, .zero, .half, .one_quarter, .two_quarters); + if (oct.@"4") fill(metrics, canvas, .half, .full, .one_quarter, .two_quarters); + if (oct.@"5") fill(metrics, canvas, .zero, .half, .two_quarters, .three_quarters); + if (oct.@"6") fill(metrics, canvas, .half, .full, .two_quarters, .three_quarters); + if (oct.@"7") fill(metrics, canvas, .zero, .half, .three_quarters, .end); + if (oct.@"8") fill(metrics, canvas, .half, .full, .three_quarters, .end); } // Separated Block Quadrants @@ -213,37 +211,37 @@ pub fn draw1CC30_1CC3F( ) !void { switch (cp) { // 𜰰 UPPER LEFT TWELFTH CIRCLE - 0x1CC30 => try circlePiece(canvas, width, height, metrics, 0, 0, 2, 2), + 0x1CC30 => try circlePiece(canvas, width, height, metrics, 0, 0, 2, 2, .tl), // 𜰱 UPPER CENTRE LEFT TWELFTH CIRCLE - 0x1CC31 => try circlePiece(canvas, width, height, metrics, 1, 0, 2, 2), + 0x1CC31 => try circlePiece(canvas, width, height, metrics, 1, 0, 2, 2, .tl), // 𜰲 UPPER CENTRE RIGHT TWELFTH CIRCLE - 0x1CC32 => try circlePiece(canvas, width, height, metrics, 2, 0, 2, 2), + 0x1CC32 => try circlePiece(canvas, width, height, metrics, 2, 0, 2, 2, .tr), // 𜰳 UPPER RIGHT TWELFTH CIRCLE - 0x1CC33 => try circlePiece(canvas, width, height, metrics, 3, 0, 2, 2), + 0x1CC33 => try circlePiece(canvas, width, height, metrics, 3, 0, 2, 2, .tr), // 𜰴 UPPER MIDDLE LEFT TWELFTH CIRCLE - 0x1CC34 => try circlePiece(canvas, width, height, metrics, 0, 1, 2, 2), + 0x1CC34 => try circlePiece(canvas, width, height, metrics, 0, 1, 2, 2, .tl), // 𜰵 UPPER LEFT QUARTER CIRCLE - 0x1CC35 => try circlePiece(canvas, width, height, metrics, 0, 0, 1, 1), + 0x1CC35 => try circlePiece(canvas, width, height, metrics, 0, 0, 1, 1, .tl), // 𜰶 UPPER RIGHT QUARTER CIRCLE - 0x1CC36 => try circlePiece(canvas, width, height, metrics, 1, 0, 1, 1), + 0x1CC36 => try circlePiece(canvas, width, height, metrics, 1, 0, 1, 1, .tr), // 𜰷 UPPER MIDDLE RIGHT TWELFTH CIRCLE - 0x1CC37 => try circlePiece(canvas, width, height, metrics, 3, 1, 2, 2), + 0x1CC37 => try circlePiece(canvas, width, height, metrics, 3, 1, 2, 2, .tr), // 𜰸 LOWER MIDDLE LEFT TWELFTH CIRCLE - 0x1CC38 => try circlePiece(canvas, width, height, metrics, 0, 2, 2, 2), + 0x1CC38 => try circlePiece(canvas, width, height, metrics, 0, 2, 2, 2, .bl), // 𜰹 LOWER LEFT QUARTER CIRCLE - 0x1CC39 => try circlePiece(canvas, width, height, metrics, 0, 1, 1, 1), + 0x1CC39 => try circlePiece(canvas, width, height, metrics, 0, 1, 1, 1, .bl), // 𜰺 LOWER RIGHT QUARTER CIRCLE - 0x1CC3A => try circlePiece(canvas, width, height, metrics, 1, 1, 1, 1), + 0x1CC3A => try circlePiece(canvas, width, height, metrics, 1, 1, 1, 1, .br), // 𜰻 LOWER MIDDLE RIGHT TWELFTH CIRCLE - 0x1CC3B => try circlePiece(canvas, width, height, metrics, 3, 2, 2, 2), + 0x1CC3B => try circlePiece(canvas, width, height, metrics, 3, 2, 2, 2, .br), // 𜰼 LOWER LEFT TWELFTH CIRCLE - 0x1CC3C => try circlePiece(canvas, width, height, metrics, 0, 3, 2, 2), + 0x1CC3C => try circlePiece(canvas, width, height, metrics, 0, 3, 2, 2, .bl), // 𜰽 LOWER CENTRE LEFT TWELFTH CIRCLE - 0x1CC3D => try circlePiece(canvas, width, height, metrics, 1, 3, 2, 2), + 0x1CC3D => try circlePiece(canvas, width, height, metrics, 1, 3, 2, 2, .bl), // 𜰾 LOWER CENTRE RIGHT TWELFTH CIRCLE - 0x1CC3E => try circlePiece(canvas, width, height, metrics, 2, 3, 2, 2), + 0x1CC3E => try circlePiece(canvas, width, height, metrics, 2, 3, 2, 2, .br), // 𜰿 LOWER RIGHT TWELFTH CIRCLE - 0x1CC3F => try circlePiece(canvas, width, height, metrics, 3, 3, 2, 2), + 0x1CC3F => try circlePiece(canvas, width, height, metrics, 3, 3, 2, 2, .br), else => unreachable, } } @@ -288,6 +286,62 @@ pub fn draw1CC1B_1CC1E( } } +/// 𜸀 RIGHT HALF AND LEFT HALF WHITE CIRCLE +pub fn draw1CE00( + cp: u32, + canvas: *font.sprite.Canvas, + width: u32, + height: u32, + metrics: font.Metrics, +) !void { + _ = cp; + _ = width; + _ = height; + sflc.circle(metrics, canvas, .left, false); + sflc.circle(metrics, canvas, .right, false); +} + +/// 𜸁 LOWER HALF AND UPPER HALF WHITE CIRCLE +pub fn draw1CE01( + cp: u32, + canvas: *font.sprite.Canvas, + width: u32, + height: u32, + metrics: font.Metrics, +) !void { + _ = cp; + _ = width; + _ = height; + sflc.circle(metrics, canvas, .top, false); + sflc.circle(metrics, canvas, .bottom, false); +} + +/// 𜸋 LEFT HALF WHITE ELLIPSE +pub fn draw1CE0B( + cp: u32, + canvas: *font.sprite.Canvas, + width: u32, + height: u32, + metrics: font.Metrics, +) !void { + _ = cp; + try circlePiece(canvas, width, height, metrics, 0, 0, 1, 0.5, .tl); + try circlePiece(canvas, width, height, metrics, 0, 0, 1, 0.5, .bl); +} + +/// 𜸌 RIGHT HALF WHITE ELLIPSE +pub fn draw1CE0C( + cp: u32, + canvas: *font.sprite.Canvas, + width: u32, + height: u32, + metrics: font.Metrics, +) !void { + _ = cp; + try circlePiece(canvas, width, height, metrics, 1, 0, 1, 0.5, .tr); + try circlePiece(canvas, width, height, metrics, 1, 0, 1, 0.5, .br); +} + pub fn draw1CE16_1CE19( cp: u32, canvas: *font.sprite.Canvas, @@ -403,6 +457,88 @@ pub fn draw1CE51_1CE8F( ); } +/// Sixteenth Blocks +pub fn draw1CE90_1CEAF( + cp: u32, + canvas: *font.sprite.Canvas, + width: u32, + height: u32, + metrics: font.Metrics, +) !void { + _ = width; + _ = height; + const q = Fraction.quarters; + switch (cp) { + // 𜺐 UPPER LEFT ONE SIXTEENTH BLOCK + 0x1CE90 => fill(metrics, canvas, q[0], q[1], q[0], q[1]), + // 𜺑 UPPER CENTRE LEFT ONE SIXTEENTH BLOCK + 0x1CE91 => fill(metrics, canvas, q[1], q[2], q[0], q[1]), + // 𜺒 UPPER CENTRE RIGHT ONE SIXTEENTH BLOCK + 0x1CE92 => fill(metrics, canvas, q[2], q[3], q[0], q[1]), + // 𜺓 UPPER RIGHT ONE SIXTEENTH BLOCK + 0x1CE93 => fill(metrics, canvas, q[3], q[4], q[0], q[1]), + // 𜺔 UPPER MIDDLE LEFT ONE SIXTEENTH BLOCK + 0x1CE94 => fill(metrics, canvas, q[0], q[1], q[1], q[2]), + // 𜺕 UPPER MIDDLE CENTRE LEFT ONE SIXTEENTH BLOCK + 0x1CE95 => fill(metrics, canvas, q[1], q[2], q[1], q[2]), + // 𜺖 UPPER MIDDLE CENTRE RIGHT ONE SIXTEENTH BLOCK + 0x1CE96 => fill(metrics, canvas, q[2], q[3], q[1], q[2]), + // 𜺗 UPPER MIDDLE RIGHT ONE SIXTEENTH BLOCK + 0x1CE97 => fill(metrics, canvas, q[3], q[4], q[1], q[2]), + // 𜺘 LOWER MIDDLE LEFT ONE SIXTEENTH BLOCK + 0x1CE98 => fill(metrics, canvas, q[0], q[1], q[2], q[3]), + // 𜺙 LOWER MIDDLE CENTRE LEFT ONE SIXTEENTH BLOCK + 0x1CE99 => fill(metrics, canvas, q[1], q[2], q[2], q[3]), + // 𜺚 LOWER MIDDLE CENTRE RIGHT ONE SIXTEENTH BLOCK + 0x1CE9A => fill(metrics, canvas, q[2], q[3], q[2], q[3]), + // 𜺛 LOWER MIDDLE RIGHT ONE SIXTEENTH BLOCK + 0x1CE9B => fill(metrics, canvas, q[3], q[4], q[2], q[3]), + // 𜺜 LOWER LEFT ONE SIXTEENTH BLOCK + 0x1CE9C => fill(metrics, canvas, q[0], q[1], q[3], q[4]), + // 𜺝 LOWER CENTRE LEFT ONE SIXTEENTH BLOCK + 0x1CE9D => fill(metrics, canvas, q[1], q[2], q[3], q[4]), + // 𜺞 LOWER CENTRE RIGHT ONE SIXTEENTH BLOCK + 0x1CE9E => fill(metrics, canvas, q[2], q[3], q[3], q[4]), + // 𜺟 LOWER RIGHT ONE SIXTEENTH BLOCK + 0x1CE9F => fill(metrics, canvas, q[3], q[4], q[3], q[4]), + + // 𜺠 RIGHT HALF LOWER ONE QUARTER BLOCK + 0x1CEA0 => fill(metrics, canvas, q[2], q[4], q[3], q[4]), + // 𜺡 RIGHT THREE QUARTERS LOWER ONE QUARTER BLOCK + 0x1CEA1 => fill(metrics, canvas, q[1], q[4], q[3], q[4]), + // 𜺢 LEFT THREE QUARTERS LOWER ONE QUARTER BLOCK + 0x1CEA2 => fill(metrics, canvas, q[0], q[3], q[3], q[4]), + // 𜺣 LEFT HALF LOWER ONE QUARTER BLOCK + 0x1CEA3 => fill(metrics, canvas, q[0], q[2], q[3], q[4]), + // 𜺤 LOWER HALF LEFT ONE QUARTER BLOCK + 0x1CEA4 => fill(metrics, canvas, q[0], q[1], q[2], q[4]), + // 𜺥 LOWER THREE QUARTERS LEFT ONE QUARTER BLOCK + 0x1CEA5 => fill(metrics, canvas, q[0], q[1], q[1], q[4]), + // 𜺦 UPPER THREE QUARTERS LEFT ONE QUARTER BLOCK + 0x1CEA6 => fill(metrics, canvas, q[0], q[1], q[0], q[3]), + // 𜺧 UPPER HALF LEFT ONE QUARTER BLOCK + 0x1CEA7 => fill(metrics, canvas, q[0], q[1], q[0], q[2]), + // 𜺨 LEFT HALF UPPER ONE QUARTER BLOCK + 0x1CEA8 => fill(metrics, canvas, q[0], q[2], q[0], q[1]), + // 𜺩 LEFT THREE QUARTERS UPPER ONE QUARTER BLOCK + 0x1CEA9 => fill(metrics, canvas, q[0], q[3], q[0], q[1]), + // 𜺪 RIGHT THREE QUARTERS UPPER ONE QUARTER BLOCK + 0x1CEAA => fill(metrics, canvas, q[1], q[4], q[0], q[1]), + // 𜺫 RIGHT HALF UPPER ONE QUARTER BLOCK + 0x1CEAB => fill(metrics, canvas, q[2], q[4], q[0], q[1]), + // 𜺬 UPPER HALF RIGHT ONE QUARTER BLOCK + 0x1CEAC => fill(metrics, canvas, q[3], q[4], q[0], q[2]), + // 𜺭 UPPER THREE QUARTERS RIGHT ONE QUARTER BLOCK + 0x1CEAD => fill(metrics, canvas, q[3], q[4], q[0], q[3]), + // 𜺮 LOWER THREE QUARTERS RIGHT ONE QUARTER BLOCK + 0x1CEAE => fill(metrics, canvas, q[3], q[4], q[1], q[4]), + // 𜺯 LOWER HALF RIGHT ONE QUARTER BLOCK + 0x1CEAF => fill(metrics, canvas, q[3], q[4], q[2], q[4]), + + else => unreachable, + } +} + fn circlePiece( canvas: *font.sprite.Canvas, width: u32, @@ -412,6 +548,7 @@ fn circlePiece( y: f64, w: f64, h: f64, + corner: Corner, ) !void { // Radius in pixels of the arc we need to draw. const wdth: f64 = @as(f64, @floatFromInt(width)) * w; @@ -437,9 +574,8 @@ fn circlePiece( var path = canvas.staticPath(2); - if (xp < wdth) { - if (yp < hght) { - // Upper left arc. + switch (corner) { + .tl => { path.moveTo(wdth - xp, ht - yp); path.curveTo( wdth - cw - xp, @@ -449,8 +585,19 @@ fn circlePiece( ht - xp, hght - yp, ); - } else { - // Lower left arc. + }, + .tr => { + path.moveTo(wdth - xp, ht - yp); + path.curveTo( + wdth + cw - xp, + ht - yp, + wdth * 2 - ht - xp, + hght - ch - yp, + wdth * 2 - ht - xp, + hght - yp, + ); + }, + .bl => { path.moveTo(ht - xp, hght - yp); path.curveTo( ht - xp, @@ -460,21 +607,8 @@ fn circlePiece( wdth - xp, hght * 2 - ht - yp, ); - } - } else { - if (yp < hght) { - // Upper right arc. - path.moveTo(wdth - xp, ht - yp); - path.curveTo( - wdth + cw - xp, - ht - yp, - wdth * 2 - ht - xp, - hght - ch - yp, - wdth * 2 - ht - xp, - hght - yp, - ); - } else { - // Lower right arc. + }, + .br => { path.moveTo(wdth * 2 - ht - xp, hght - yp); path.curveTo( wdth * 2 - ht - xp, @@ -484,7 +618,7 @@ fn circlePiece( wdth - xp, hght * 2 - ht - yp, ); - } + }, } try canvas.strokePath(path.wrapped_path, .{ diff --git a/src/font/sprite/testdata/U+1CE00...U+1CEFF-11x21+2.png b/src/font/sprite/testdata/U+1CE00...U+1CEFF-11x21+2.png index 03305c81c..b3cda82d1 100644 Binary files a/src/font/sprite/testdata/U+1CE00...U+1CEFF-11x21+2.png and b/src/font/sprite/testdata/U+1CE00...U+1CEFF-11x21+2.png differ diff --git a/src/font/sprite/testdata/U+1CE00...U+1CEFF-12x24+3.png b/src/font/sprite/testdata/U+1CE00...U+1CEFF-12x24+3.png index c17e08c39..e076da7c5 100644 Binary files a/src/font/sprite/testdata/U+1CE00...U+1CEFF-12x24+3.png and b/src/font/sprite/testdata/U+1CE00...U+1CEFF-12x24+3.png differ diff --git a/src/font/sprite/testdata/U+1CE00...U+1CEFF-18x36+4.png b/src/font/sprite/testdata/U+1CE00...U+1CEFF-18x36+4.png index 6f4a004d4..366be3867 100644 Binary files a/src/font/sprite/testdata/U+1CE00...U+1CEFF-18x36+4.png and b/src/font/sprite/testdata/U+1CE00...U+1CEFF-18x36+4.png differ diff --git a/src/font/sprite/testdata/U+1CE00...U+1CEFF-9x17+1.png b/src/font/sprite/testdata/U+1CE00...U+1CEFF-9x17+1.png index a822c4f58..5cd7a4efe 100644 Binary files a/src/font/sprite/testdata/U+1CE00...U+1CEFF-9x17+1.png and b/src/font/sprite/testdata/U+1CE00...U+1CEFF-9x17+1.png differ diff --git a/src/font/sprite/testdata/U+1FB00...U+1FBFF-11x21+2.png b/src/font/sprite/testdata/U+1FB00...U+1FBFF-11x21+2.png index ecf6eae26..023396feb 100644 Binary files a/src/font/sprite/testdata/U+1FB00...U+1FBFF-11x21+2.png and b/src/font/sprite/testdata/U+1FB00...U+1FBFF-11x21+2.png differ diff --git a/src/font/sprite/testdata/U+1FB00...U+1FBFF-12x24+3.png b/src/font/sprite/testdata/U+1FB00...U+1FBFF-12x24+3.png index 35504e45b..2eff59c76 100644 Binary files a/src/font/sprite/testdata/U+1FB00...U+1FBFF-12x24+3.png and b/src/font/sprite/testdata/U+1FB00...U+1FBFF-12x24+3.png differ diff --git a/src/font/sprite/testdata/U+1FB00...U+1FBFF-18x36+4.png b/src/font/sprite/testdata/U+1FB00...U+1FBFF-18x36+4.png index e1a9e7841..b77f7dfae 100644 Binary files a/src/font/sprite/testdata/U+1FB00...U+1FBFF-18x36+4.png and b/src/font/sprite/testdata/U+1FB00...U+1FBFF-18x36+4.png differ diff --git a/src/font/sprite/testdata/U+1FB00...U+1FBFF-9x17+1.png b/src/font/sprite/testdata/U+1FB00...U+1FBFF-9x17+1.png index 3fa06a8fc..062a7da81 100644 Binary files a/src/font/sprite/testdata/U+1FB00...U+1FBFF-9x17+1.png and b/src/font/sprite/testdata/U+1FB00...U+1FBFF-9x17+1.png differ diff --git a/typos.toml b/typos.toml index a8b296755..1fb54ecc6 100644 --- a/typos.toml +++ b/typos.toml @@ -39,8 +39,6 @@ extend-ignore-re = [ [default.extend-words] Pn = "Pn" thr = "thr" -# Should be "halves", but for now skip it as it would make diff huge -halfs = "halfs" # Swift oddities Requestor = "Requestor" iterm = "iterm"