Even More Sprite Glyphs (#7761)
Follow-on to #7755, adds the sixteenth blocks from the Symbols for Legacy Computing Supplement and a few circle/ellipse glyphs that connect to existing glyphs. In order to add the one sixteenth blocks I reworked block element alignment to not use the `yHalfs`, `yThirds`, etc. functions, but instead a more versatile `Fraction` type I introduced, and making these changes slightly affected how the vertical/horizontal eighths glyphs are sized, and the horizontal center-point alignment of the smooth mosaic glyphs for odd cell widths (shifted by half a pixel), but I believe both of these to be improvements. ### Circle/ellipse glyphs ``` Existing sprites: Which connect like so: New sprites: Which connect like so: ``` |Main (via font)|This PR (via sprites)| |-|-| ||| ### Diffs |Range||||| |-|-|-|-|-| |U+1CE00...U+1CEFF||||| |U+1FB00...U+1FBFF|||||pull/7783/head
|
|
@ -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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
};
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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, .{
|
||||
|
|
|
|||
|
Before Width: | Height: | Size: 632 B After Width: | Height: | Size: 1006 B |
|
Before Width: | Height: | Size: 819 B After Width: | Height: | Size: 1.2 KiB |
|
Before Width: | Height: | Size: 1.5 KiB After Width: | Height: | Size: 2.2 KiB |
|
Before Width: | Height: | Size: 443 B After Width: | Height: | Size: 751 B |
|
Before Width: | Height: | Size: 5.3 KiB After Width: | Height: | Size: 5.3 KiB |
|
Before Width: | Height: | Size: 5.6 KiB After Width: | Height: | Size: 5.6 KiB |
|
Before Width: | Height: | Size: 9.7 KiB After Width: | Height: | Size: 9.7 KiB |
|
Before Width: | Height: | Size: 4.2 KiB After Width: | Height: | Size: 4.2 KiB |
|
|
@ -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"
|
||||
|
|
|
|||