Add Fraktur e/o/ø (#2445)

* Add
  - LATIN SMALL LETTER BLACKLETTER E (`U+AB32`).
  - LATIN SMALL LETTER BLACKLETTER O (`U+AB3D`).
  - LATIN SMALL LETTER BLACKLETTER O WITH STROKE (`U+AB3E`).
  - MATHEMATICAL FRAKTUR SMALL E (`U+1D522`).
  - MATHEMATICAL FRAKTUR SMALL O (`U+1D52C`).

* Notes (#2443, #444)

* Refine
This commit is contained in:
Belleve 2024-07-30 02:28:53 -10:00 committed by GitHub
parent edfd04dae6
commit 67f12d42af
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
11 changed files with 382 additions and 119 deletions

View file

@ -3,6 +3,7 @@
"version": "31.1.0",
"private": true,
"exports": {
"./derived-coordinates": "./src/derived-coordinates.mjs",
"./boole-kit": "./src/boole-kit.mjs",
"./spiro-kit": "./src/spiro-kit.mjs"
},

View file

@ -0,0 +1,171 @@
import {
DecorInterpolator,
DEP_POST_X,
DEP_POST_Y,
DEP_PRE_X,
DEP_PRE_Y,
DEP_SAME_X,
DEP_SAME_Y,
DerivedCoordinateBase,
InterpolatorBase,
} from "@iosevka/geometry/spiro-control";
const TINY = 1 / 128;
export function SetupBuilders(_bindings) {
return {
// Derived coordinates
// pre@, post@: copy or ade delta to the pre or post point's X or Y coordinate
// use with pre@ or like (pre@ <+> delta)
"pre@": new CDeltaPre(0),
"post@": new CDeltaPost(0),
// "Tangent" derived cooredinates, which is simply a tiny delta.
"pre@tang-out": s => new CDeltaPre(TINY * s),
"post@tang-out": s => new CDeltaPost(TINY * s),
"pre@tang-in": s => new CDeltaPre(-TINY * s),
"post@tang-in": s => new CDeltaPost(-TINY * s),
// mix@: mix between pre and post point's X or Y coordinates
// usage [mix@ proportion] or [mix@ proportion delta]
"mix@": (p, delta) => new CMixCoord(p, delta),
// pre@slope, post@slope: Get the coordiante using the pre/post point's coordinate and a
// slope. An optional delta can be added to the result. See the definitions for more
// details.
"pre@slope": (s, delta) => new CAtSlopePre(s, delta),
"post@slope": (s, delta) => new CAtSlopePost(s, delta),
// Interpolators
// decor@, decor@@, decor@@@: Add a "delay" to the thing inside when resolving the spiro
// controls. This is a very useful utility for coordinate propagation, which allow us to
// "skip" the current point and go to the next or previous point. The number of @'s
// determines the number of times the delay is applied.
"decor@": x => new DecorInterpolator(x),
"decor@@": x => new DecorInterpolator(new DecorInterpolator(x)),
"decor@@@": x => new DecorInterpolator(new DecorInterpolator(new DecorInterpolator(x))),
};
}
class CDeltaPre extends DerivedCoordinateBase {
constructor(delta) {
super();
this.delta = delta;
}
op_add(delta) {
return new CDeltaPre(this.delta + delta);
}
op_sub(delta) {
return new CDeltaPre(this.delta - delta);
}
getDependencyForX() {
return DEP_PRE_X;
}
getDependencyForY() {
return DEP_PRE_Y;
}
resolveX(pre, curr, post) {
return pre.x + this.delta;
}
resolveY(pre, curr, post) {
return pre.y + this.delta;
}
}
class CDeltaPost extends DerivedCoordinateBase {
constructor(delta) {
super();
this.delta = delta;
}
op_add(delta) {
return new CDeltaPost(this.delta + delta);
}
op_sub(delta) {
return new CDeltaPost(this.delta - delta);
}
getDependencyForX() {
return DEP_POST_X;
}
getDependencyForY() {
return DEP_POST_Y;
}
resolveX(pre, curr, post) {
return post.x + this.delta;
}
resolveY(pre, curr, post) {
return post.y + this.delta;
}
}
export class CMixCoord extends DerivedCoordinateBase {
constructor(proportion, delta, mockPre, mockPost) {
super();
this.proportion = proportion;
this.delta = delta || 0;
this.mockPre = mockPre || null;
this.mockPost = mockPost || null;
}
getDependencyForX() {
let f = 0;
if (!this.mockPre) f |= DEP_PRE_X;
if (!this.mockPost) f |= DEP_POST_X;
return f;
}
getDependencyForY() {
let f = 0;
if (!this.mockPre) f |= DEP_PRE_Y;
if (!this.mockPost) f |= DEP_POST_Y;
return f;
}
resolveX(_pre, curr, _post) {
const pre = this.mockPre || _pre;
const post = this.mockPost || _post;
return pre.x + this.proportion * (post.x - pre.x) + this.delta;
}
resolveY(_pre, curr, _post) {
const pre = this.mockPre || _pre;
const post = this.mockPost || _post;
return pre.y + this.proportion * (post.y - pre.y) + this.delta;
}
}
class CAtSlopePre extends DerivedCoordinateBase {
constructor(slope, delta) {
super();
this.slope = slope;
this.delta = delta || 0;
}
getDependencyForX() {
return DEP_PRE_X | DEP_PRE_Y | DEP_SAME_Y;
}
getDependencyForY() {
return DEP_PRE_X | DEP_PRE_Y | DEP_SAME_X;
}
resolveY(pre, curr, post) {
return pre.y + this.slope * (curr.x - pre.x) + this.delta;
}
resolveX(pre, curr, post) {
return pre.x + (curr.y - pre.y) / this.slope + this.delta;
}
}
class CAtSlopePost extends DerivedCoordinateBase {
constructor(slope, delta) {
super();
this.slope = slope;
this.delta = delta || 0;
}
getDependencyForX() {
return DEP_POST_X | DEP_POST_Y | DEP_SAME_Y;
}
getDependencyForY() {
return DEP_POST_X | DEP_POST_Y | DEP_SAME_X;
}
resolveY(pre, curr, post) {
return post.y + this.slope * (curr.x - post.x) + this.delta;
}
resolveX(pre, curr, post) {
return post.x + (curr.y - post.y) / this.slope + this.delta;
}
}

View file

@ -1,11 +1,6 @@
import { DiSpiroGeometry, SpiroGeometry } from "@iosevka/geometry";
import {
BiKnotCollector,
DEP_POST_X,
DEP_POST_Y,
DEP_PRE_X,
DEP_PRE_Y,
DerivedCoordinateBase,
Interpolator,
SpiroFlattener,
TerminateInstruction,
@ -109,40 +104,6 @@ function DirPairImpl(kPre, kCenter, kPost, dirX, dirY, dPre, dPost) {
new UserCloseKnotPair(kCenter(x, y, af), tyPre, tyPost, dirX, dirY, dPre, dPost);
}
/// Derivative coordinates
class CSameX extends DerivedCoordinateBase {
getDependency() {
return DEP_PRE_X;
}
resolve(pre) {
return pre.x;
}
}
class CSameY extends DerivedCoordinateBase {
getDependency() {
return DEP_PRE_Y;
}
resolve(pre) {
return pre.y;
}
}
class CSameXPost extends DerivedCoordinateBase {
getDependency() {
return DEP_POST_X;
}
resolve(pre, curr, post) {
return post.x;
}
}
class CSameYPost extends DerivedCoordinateBase {
getDependency() {
return DEP_POST_Y;
}
resolve(pre, curr, post) {
return post.y;
}
}
export function SetupBuilders(bindings) {
const { Stroke, Superness } = bindings;
@ -193,7 +154,7 @@ export function SetupBuilders(bindings) {
{ name: "ld", x: -1, y: -1 },
];
for (const [sink, kl, kc, kr] of knotTypes) {
sink.sl = s => new DirectedKnotPairBuilder(bindings, kl, kc, kr, -1, s);
sink.sl = s => new DirectedKnotPairBuilder(bindings, kl, kc, kr, -1, -s);
sink.sr = s => new DirectedKnotPairBuilder(bindings, kl, kc, kr, 1, s);
sink.dir = (dx, dy) => new DirectedKnotPairBuilder(bindings, kl, kc, kr, dx, dy);
for (const d of directions) {
@ -479,10 +440,5 @@ export function SetupBuilders(bindings) {
dispiro,
"spiro-outline": spiroOutline,
"spiro-collect": spiroCollect,
"same-x": new CSameX(),
"same-y": new CSameY(),
"same-x-post": new CSameXPost(),
"same-y-post": new CSameYPost(),
};
}