Make the geometry cache more efficient. Bump version. (#2270)
This commit is contained in:
parent
c9d9ee2319
commit
4f2f0d973c
21 changed files with 360 additions and 247 deletions
80
package-lock.json
generated
80
package-lock.json
generated
|
@ -1,12 +1,12 @@
|
||||||
{
|
{
|
||||||
"name": "@iosevka/monorepo",
|
"name": "@iosevka/monorepo",
|
||||||
"version": "29.0.5",
|
"version": "29.0.6",
|
||||||
"lockfileVersion": 3,
|
"lockfileVersion": 3,
|
||||||
"requires": true,
|
"requires": true,
|
||||||
"packages": {
|
"packages": {
|
||||||
"": {
|
"": {
|
||||||
"name": "@iosevka/monorepo",
|
"name": "@iosevka/monorepo",
|
||||||
"version": "29.0.5",
|
"version": "29.0.6",
|
||||||
"workspaces": [
|
"workspaces": [
|
||||||
"packages/*",
|
"packages/*",
|
||||||
"tools/*"
|
"tools/*"
|
||||||
|
@ -4310,16 +4310,16 @@
|
||||||
},
|
},
|
||||||
"packages/font": {
|
"packages/font": {
|
||||||
"name": "@iosevka/font",
|
"name": "@iosevka/font",
|
||||||
"version": "29.0.5",
|
"version": "29.0.6",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@iarna/toml": "^2.2.5",
|
"@iarna/toml": "^2.2.5",
|
||||||
"@iosevka/font-glyphs": "29.0.5",
|
"@iosevka/font-glyphs": "29.0.6",
|
||||||
"@iosevka/font-otl": "29.0.5",
|
"@iosevka/font-otl": "29.0.6",
|
||||||
"@iosevka/geometry": "29.0.5",
|
"@iosevka/geometry": "29.0.6",
|
||||||
"@iosevka/geometry-cache": "29.0.5",
|
"@iosevka/geometry-cache": "29.0.6",
|
||||||
"@iosevka/glyph": "29.0.5",
|
"@iosevka/glyph": "29.0.6",
|
||||||
"@iosevka/param": "29.0.5",
|
"@iosevka/param": "29.0.6",
|
||||||
"@iosevka/util": "29.0.5",
|
"@iosevka/util": "29.0.6",
|
||||||
"harfbuzzjs": "^0.3.4",
|
"harfbuzzjs": "^0.3.4",
|
||||||
"ot-builder": "^1.7.3",
|
"ot-builder": "^1.7.3",
|
||||||
"semver": "^7.6.0"
|
"semver": "^7.6.0"
|
||||||
|
@ -4327,100 +4327,100 @@
|
||||||
},
|
},
|
||||||
"packages/font-glyphs": {
|
"packages/font-glyphs": {
|
||||||
"name": "@iosevka/font-glyphs",
|
"name": "@iosevka/font-glyphs",
|
||||||
"version": "29.0.5",
|
"version": "29.0.6",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@iosevka/font-kits": "29.0.5",
|
"@iosevka/font-kits": "29.0.6",
|
||||||
"@iosevka/geometry": "29.0.5",
|
"@iosevka/geometry": "29.0.6",
|
||||||
"@iosevka/geometry-cache": "29.0.5",
|
"@iosevka/geometry-cache": "29.0.6",
|
||||||
"@iosevka/glyph": "29.0.5",
|
"@iosevka/glyph": "29.0.6",
|
||||||
"@iosevka/util": "29.0.5",
|
"@iosevka/util": "29.0.6",
|
||||||
"typo-geom": "^0.15.1"
|
"typo-geom": "^0.15.1"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"packages/font-kits": {
|
"packages/font-kits": {
|
||||||
"name": "@iosevka/font-kits",
|
"name": "@iosevka/font-kits",
|
||||||
"version": "29.0.5",
|
"version": "29.0.6",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@iosevka/geometry": "29.0.5",
|
"@iosevka/geometry": "29.0.6",
|
||||||
"@iosevka/glyph": "29.0.5",
|
"@iosevka/glyph": "29.0.6",
|
||||||
"@iosevka/util": "29.0.5"
|
"@iosevka/util": "29.0.6"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"packages/font-otl": {
|
"packages/font-otl": {
|
||||||
"name": "@iosevka/font-otl",
|
"name": "@iosevka/font-otl",
|
||||||
"version": "29.0.5",
|
"version": "29.0.6",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@iosevka/font-glyphs": "29.0.5",
|
"@iosevka/font-glyphs": "29.0.6",
|
||||||
"@iosevka/glyph": "29.0.5",
|
"@iosevka/glyph": "29.0.6",
|
||||||
"toposort": "^2.0.2"
|
"toposort": "^2.0.2"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"packages/geometry": {
|
"packages/geometry": {
|
||||||
"name": "@iosevka/geometry",
|
"name": "@iosevka/geometry",
|
||||||
"version": "29.0.5",
|
"version": "29.0.6",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@iosevka/util": "29.0.5",
|
"@iosevka/util": "29.0.6",
|
||||||
"spiro": "^3.0.0",
|
"spiro": "^3.0.0",
|
||||||
"typo-geom": "^0.15.1"
|
"typo-geom": "^0.15.1"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"packages/geometry-cache": {
|
"packages/geometry-cache": {
|
||||||
"name": "@iosevka/geometry-cache",
|
"name": "@iosevka/geometry-cache",
|
||||||
"version": "29.0.5",
|
"version": "29.0.6",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@iosevka/geometry": "29.0.5",
|
"@iosevka/geometry": "29.0.6",
|
||||||
"@msgpack/msgpack": "^2.8.0"
|
"@msgpack/msgpack": "^2.8.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"packages/glyph": {
|
"packages/glyph": {
|
||||||
"name": "@iosevka/glyph",
|
"name": "@iosevka/glyph",
|
||||||
"version": "29.0.5",
|
"version": "29.0.6",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@iosevka/geometry": "29.0.5"
|
"@iosevka/geometry": "29.0.6"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"packages/param": {
|
"packages/param": {
|
||||||
"name": "@iosevka/param",
|
"name": "@iosevka/param",
|
||||||
"version": "29.0.5",
|
"version": "29.0.6",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@iosevka/util": "29.0.5"
|
"@iosevka/util": "29.0.6"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"packages/util": {
|
"packages/util": {
|
||||||
"name": "@iosevka/util",
|
"name": "@iosevka/util",
|
||||||
"version": "29.0.5"
|
"version": "29.0.6"
|
||||||
},
|
},
|
||||||
"tools/amend-readme": {
|
"tools/amend-readme": {
|
||||||
"name": "@iosevka/amend-readme",
|
"name": "@iosevka/amend-readme",
|
||||||
"version": "29.0.5",
|
"version": "29.0.6",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@iarna/toml": "^2.2.5",
|
"@iarna/toml": "^2.2.5",
|
||||||
"@iosevka/param": "29.0.5",
|
"@iosevka/param": "29.0.6",
|
||||||
"@unicode/unicode-15.1.0": "^1.5.2"
|
"@unicode/unicode-15.1.0": "^1.5.2"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"tools/data-export": {
|
"tools/data-export": {
|
||||||
"name": "@iosevka/data-export",
|
"name": "@iosevka/data-export",
|
||||||
"version": "29.0.5",
|
"version": "29.0.6",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@iarna/toml": "^2.2.5",
|
"@iarna/toml": "^2.2.5",
|
||||||
"@iosevka/param": "29.0.5",
|
"@iosevka/param": "29.0.6",
|
||||||
"@unicode/unicode-15.1.0": "^1.5.2",
|
"@unicode/unicode-15.1.0": "^1.5.2",
|
||||||
"cldr": "^7.5.0"
|
"cldr": "^7.5.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"tools/generate-samples": {
|
"tools/generate-samples": {
|
||||||
"name": "@iosevka/generate-samples",
|
"name": "@iosevka/generate-samples",
|
||||||
"version": "29.0.5",
|
"version": "29.0.6",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@iosevka/data-export": "29.0.5"
|
"@iosevka/data-export": "29.0.6"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"tools/misc": {
|
"tools/misc": {
|
||||||
"name": "@iosevka/misc",
|
"name": "@iosevka/misc",
|
||||||
"version": "29.0.5",
|
"version": "29.0.6",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@iosevka/util": "29.0.5",
|
"@iosevka/util": "29.0.6",
|
||||||
"semver": "^7.6.0",
|
"semver": "^7.6.0",
|
||||||
"wawoff2": "^2.0.1"
|
"wawoff2": "^2.0.1"
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
{
|
{
|
||||||
"name": "@iosevka/monorepo",
|
"name": "@iosevka/monorepo",
|
||||||
"version": "29.0.5",
|
"version": "29.0.6",
|
||||||
"workspaces": [
|
"workspaces": [
|
||||||
"packages/*",
|
"packages/*",
|
||||||
"tools/*"
|
"tools/*"
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
{
|
{
|
||||||
"name": "@iosevka/font-glyphs",
|
"name": "@iosevka/font-glyphs",
|
||||||
"version": "29.0.5",
|
"version": "29.0.6",
|
||||||
"private": true,
|
"private": true,
|
||||||
"exports": {
|
"exports": {
|
||||||
".": "./src/index.mjs",
|
".": "./src/index.mjs",
|
||||||
|
@ -8,11 +8,11 @@
|
||||||
"./unicode-knowledge": "./src/meta/unicode-knowledge.mjs"
|
"./unicode-knowledge": "./src/meta/unicode-knowledge.mjs"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@iosevka/font-kits": "29.0.5",
|
"@iosevka/font-kits": "29.0.6",
|
||||||
"@iosevka/geometry": "29.0.5",
|
"@iosevka/geometry": "29.0.6",
|
||||||
"@iosevka/geometry-cache": "29.0.5",
|
"@iosevka/geometry-cache": "29.0.6",
|
||||||
"@iosevka/glyph": "29.0.5",
|
"@iosevka/glyph": "29.0.6",
|
||||||
"@iosevka/util": "29.0.5",
|
"@iosevka/util": "29.0.6",
|
||||||
"typo-geom": "^0.15.1"
|
"typo-geom": "^0.15.1"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,14 +1,14 @@
|
||||||
{
|
{
|
||||||
"name": "@iosevka/font-kits",
|
"name": "@iosevka/font-kits",
|
||||||
"version": "29.0.5",
|
"version": "29.0.6",
|
||||||
"private": true,
|
"private": true,
|
||||||
"exports": {
|
"exports": {
|
||||||
"./boole-kit": "./src/boole-kit.mjs",
|
"./boole-kit": "./src/boole-kit.mjs",
|
||||||
"./spiro-kit": "./src/spiro-kit.mjs"
|
"./spiro-kit": "./src/spiro-kit.mjs"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@iosevka/geometry": "29.0.5",
|
"@iosevka/geometry": "29.0.6",
|
||||||
"@iosevka/glyph": "29.0.5",
|
"@iosevka/glyph": "29.0.6",
|
||||||
"@iosevka/util": "29.0.5"
|
"@iosevka/util": "29.0.6"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,13 +1,13 @@
|
||||||
{
|
{
|
||||||
"name": "@iosevka/font-otl",
|
"name": "@iosevka/font-otl",
|
||||||
"version": "29.0.5",
|
"version": "29.0.6",
|
||||||
"private": true,
|
"private": true,
|
||||||
"exports": {
|
"exports": {
|
||||||
".": "./src/index.mjs"
|
".": "./src/index.mjs"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@iosevka/font-glyphs": "29.0.5",
|
"@iosevka/font-glyphs": "29.0.6",
|
||||||
"@iosevka/glyph": "29.0.5",
|
"@iosevka/glyph": "29.0.6",
|
||||||
"toposort": "^2.0.2"
|
"toposort": "^2.0.2"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
{
|
{
|
||||||
"name": "@iosevka/font",
|
"name": "@iosevka/font",
|
||||||
"version": "29.0.5",
|
"version": "29.0.6",
|
||||||
"private": true,
|
"private": true,
|
||||||
"exports": {
|
"exports": {
|
||||||
".": "./src/index.mjs",
|
".": "./src/index.mjs",
|
||||||
|
@ -10,13 +10,13 @@
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@iarna/toml": "^2.2.5",
|
"@iarna/toml": "^2.2.5",
|
||||||
"@iosevka/font-glyphs": "29.0.5",
|
"@iosevka/font-glyphs": "29.0.6",
|
||||||
"@iosevka/font-otl": "29.0.5",
|
"@iosevka/font-otl": "29.0.6",
|
||||||
"@iosevka/geometry": "29.0.5",
|
"@iosevka/geometry": "29.0.6",
|
||||||
"@iosevka/geometry-cache": "29.0.5",
|
"@iosevka/geometry-cache": "29.0.6",
|
||||||
"@iosevka/glyph": "29.0.5",
|
"@iosevka/glyph": "29.0.6",
|
||||||
"@iosevka/param": "29.0.5",
|
"@iosevka/param": "29.0.6",
|
||||||
"@iosevka/util": "29.0.5",
|
"@iosevka/util": "29.0.6",
|
||||||
"harfbuzzjs": "^0.3.4",
|
"harfbuzzjs": "^0.3.4",
|
||||||
"ot-builder": "^1.7.3",
|
"ot-builder": "^1.7.3",
|
||||||
"semver": "^7.6.0"
|
"semver": "^7.6.0"
|
||||||
|
|
|
@ -19,19 +19,6 @@ function regulateGlyphStore(cache, skew, glyphStore) {
|
||||||
}
|
}
|
||||||
|
|
||||||
function flattenSimpleGlyph(cache, skew, g) {
|
function flattenSimpleGlyph(cache, skew, g) {
|
||||||
// Check if the geometry is already in the cache. If so, use the cached geometry.
|
|
||||||
const ck = Geom.hashGeometry(g.geometry);
|
|
||||||
if (ck && cache) {
|
|
||||||
const cachedGeometry = cache && cache.getGF(ck);
|
|
||||||
if (cachedGeometry) {
|
|
||||||
g.clearGeometry();
|
|
||||||
g.includeContours(cachedGeometry);
|
|
||||||
cache.refreshGF(ck);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Perform the actual simplification
|
|
||||||
try {
|
try {
|
||||||
let gSimplified;
|
let gSimplified;
|
||||||
if (skew) {
|
if (skew) {
|
||||||
|
@ -45,10 +32,9 @@ function flattenSimpleGlyph(cache, skew, g) {
|
||||||
gSimplified = new Geom.SimplifyGeometry(g.geometry);
|
gSimplified = new Geom.SimplifyGeometry(g.geometry);
|
||||||
}
|
}
|
||||||
|
|
||||||
const cs = gSimplified.toContours();
|
const cs = gSimplified.toContours({ cache });
|
||||||
g.clearGeometry();
|
g.clearGeometry();
|
||||||
g.includeContours(cs);
|
g.includeContours(cs);
|
||||||
if (ck && cache) cache.saveGF(ck, cs);
|
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
console.error("Detected broken geometry when processing", g._m_identifier);
|
console.error("Detected broken geometry when processing", g._m_identifier);
|
||||||
throw e;
|
throw e;
|
||||||
|
|
|
@ -1,12 +1,12 @@
|
||||||
{
|
{
|
||||||
"name": "@iosevka/geometry-cache",
|
"name": "@iosevka/geometry-cache",
|
||||||
"version": "29.0.5",
|
"version": "29.0.6",
|
||||||
"private": true,
|
"private": true,
|
||||||
"exports": {
|
"exports": {
|
||||||
".": "./src/index.mjs"
|
".": "./src/index.mjs"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@iosevka/geometry": "29.0.5",
|
"@iosevka/geometry": "29.0.6",
|
||||||
"@msgpack/msgpack": "^2.8.0"
|
"@msgpack/msgpack": "^2.8.0"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,7 +4,7 @@ import zlib from "zlib";
|
||||||
import * as CurveUtil from "@iosevka/geometry/curve-util";
|
import * as CurveUtil from "@iosevka/geometry/curve-util";
|
||||||
import { encode, decode } from "@msgpack/msgpack";
|
import { encode, decode } from "@msgpack/msgpack";
|
||||||
|
|
||||||
const Edition = 37;
|
const Edition = 40;
|
||||||
const MAX_AGE = 16;
|
const MAX_AGE = 16;
|
||||||
class GfEntry {
|
class GfEntry {
|
||||||
constructor(age, value) {
|
constructor(age, value) {
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
{
|
{
|
||||||
"name": "@iosevka/geometry",
|
"name": "@iosevka/geometry",
|
||||||
"version": "29.0.5",
|
"version": "29.0.6",
|
||||||
"private": true,
|
"private": true,
|
||||||
"exports": {
|
"exports": {
|
||||||
".": "./src/index.mjs",
|
".": "./src/index.mjs",
|
||||||
|
@ -13,7 +13,7 @@
|
||||||
"./spiro-control": "./src/spiro-control.mjs"
|
"./spiro-control": "./src/spiro-control.mjs"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@iosevka/util": "29.0.5",
|
"@iosevka/util": "29.0.6",
|
||||||
"spiro": "^3.0.0",
|
"spiro": "^3.0.0",
|
||||||
"typo-geom": "^0.15.1"
|
"typo-geom": "^0.15.1"
|
||||||
}
|
}
|
||||||
|
|
|
@ -13,11 +13,11 @@ import { Transform } from "./transform.mjs";
|
||||||
|
|
||||||
export const CPLX_NON_EMPTY = 0x01; // A geometry tree that is not empty
|
export const CPLX_NON_EMPTY = 0x01; // A geometry tree that is not empty
|
||||||
export const CPLX_NON_SIMPLE = 0x02; // A geometry tree that contains non-simple contours
|
export const CPLX_NON_SIMPLE = 0x02; // A geometry tree that contains non-simple contours
|
||||||
export const CPLX_BROKEN = 0x04; // A geometry tree that contains broken contours, like having points with NaN coordinates
|
export const CPLX_BROKEN = 0x04; // A geometry tree that contains broken contours
|
||||||
export const CPLX_UNKNOWN = 0xff;
|
export const CPLX_UNKNOWN = 0xff;
|
||||||
|
|
||||||
export class GeometryBase {
|
export class GeometryBase {
|
||||||
toContours() {
|
toContours(ctx) {
|
||||||
throw new Error("Unimplemented");
|
throw new Error("Unimplemented");
|
||||||
}
|
}
|
||||||
toReferences() {
|
toReferences() {
|
||||||
|
@ -35,8 +35,9 @@ export class GeometryBase {
|
||||||
measureComplexity() {
|
measureComplexity() {
|
||||||
return CPLX_UNKNOWN;
|
return CPLX_UNKNOWN;
|
||||||
}
|
}
|
||||||
toShapeStringOrNull() {
|
|
||||||
return null;
|
hash(h) {
|
||||||
|
return h.invalid();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -47,7 +48,7 @@ export class ContourSetGeometry extends GeometryBase {
|
||||||
super();
|
super();
|
||||||
this.m_contours = contours;
|
this.m_contours = contours;
|
||||||
}
|
}
|
||||||
toContours() {
|
toContours(ctx) {
|
||||||
return this.m_contours;
|
return this.m_contours;
|
||||||
}
|
}
|
||||||
toReferences() {
|
toReferences() {
|
||||||
|
@ -68,26 +69,52 @@ export class ContourSetGeometry extends GeometryBase {
|
||||||
}
|
}
|
||||||
return cp;
|
return cp;
|
||||||
}
|
}
|
||||||
toShapeStringOrNull() {
|
hash(h) {
|
||||||
return Format.struct(
|
h.beginStruct("ContourSetGeometry");
|
||||||
`ContourSetGeometry`,
|
h.beginArray(this.m_contours.length);
|
||||||
Format.list(this.m_contours.map(c => Format.list(c.map(Format.typedPoint)))),
|
for (const c of this.m_contours) {
|
||||||
);
|
h.beginArray(c.length);
|
||||||
|
for (const z of c) h.typedPoint(z);
|
||||||
|
h.endArray();
|
||||||
|
}
|
||||||
|
h.endArray();
|
||||||
|
h.endStruct();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export class SpiroGeometry extends GeometryBase {
|
// Enabling geometry cache over the deep nodes of the geometry tree
|
||||||
|
export class CachedGeometry extends GeometryBase {
|
||||||
|
toContours(ctx) {
|
||||||
|
let ck = null;
|
||||||
|
if (ctx && ctx.cache) {
|
||||||
|
ck = hashGeometry(this);
|
||||||
|
const gf = ctx.cache.getGF(ck);
|
||||||
|
if (gf) {
|
||||||
|
ctx.cache.refreshGF(ck);
|
||||||
|
return gf;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const outline = this.toContoursImpl(ctx);
|
||||||
|
if (ck && ctx && ctx.cache) ctx.cache.saveGF(ck, outline);
|
||||||
|
|
||||||
|
return outline;
|
||||||
|
}
|
||||||
|
|
||||||
|
toContoursImpl() {
|
||||||
|
throw new Error("Unimplemented");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export class SpiroGeometry extends CachedGeometry {
|
||||||
constructor(gizmo, closed, knots) {
|
constructor(gizmo, closed, knots) {
|
||||||
super();
|
super();
|
||||||
this.m_knots = knots;
|
this.m_knots = knots;
|
||||||
this.m_closed = closed;
|
this.m_closed = closed;
|
||||||
this.m_gizmo = gizmo;
|
this.m_gizmo = gizmo;
|
||||||
this.m_cachedContours = null;
|
|
||||||
}
|
}
|
||||||
toContours() {
|
toContoursImpl() {
|
||||||
if (this.m_cachedContours) return this.m_cachedContours;
|
return spiroToOutline(this.m_knots, this.m_closed, this.m_gizmo);
|
||||||
this.m_cachedContours = spiroToOutline(this.m_knots, this.m_closed, this.m_gizmo);
|
|
||||||
return this.m_cachedContours;
|
|
||||||
}
|
}
|
||||||
toReferences() {
|
toReferences() {
|
||||||
return null;
|
return null;
|
||||||
|
@ -105,28 +132,28 @@ export class SpiroGeometry extends GeometryBase {
|
||||||
}
|
}
|
||||||
return cplx;
|
return cplx;
|
||||||
}
|
}
|
||||||
toShapeStringOrNull() {
|
|
||||||
return Format.struct(
|
hash(h) {
|
||||||
"SpiroGeometry",
|
h.beginStruct("SpiroGeometry");
|
||||||
Format.gizmo(this.m_gizmo),
|
h.gizmo(this.m_gizmo);
|
||||||
this.m_closed,
|
h.bool(this.m_closed);
|
||||||
Format.list(this.m_knots.map(k => k.toShapeString())),
|
h.beginArray(this.m_knots.length);
|
||||||
);
|
for (const knot of this.m_knots) h.embed(knot);
|
||||||
|
h.endArray();
|
||||||
|
h.endStruct();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export class DiSpiroGeometry extends GeometryBase {
|
export class DiSpiroGeometry extends CachedGeometry {
|
||||||
constructor(gizmo, contrast, closed, biKnots) {
|
constructor(gizmo, contrast, closed, biKnots) {
|
||||||
super();
|
super();
|
||||||
this.m_biKnots = biKnots; // untransformed
|
this.m_biKnots = biKnots; // untransformed
|
||||||
this.m_closed = closed;
|
this.m_closed = closed;
|
||||||
this.m_gizmo = gizmo;
|
this.m_gizmo = gizmo;
|
||||||
this.m_contrast = contrast;
|
this.m_contrast = contrast;
|
||||||
this.m_cachedExpansionResults = null;
|
|
||||||
this.m_cachedContours = null;
|
|
||||||
}
|
}
|
||||||
toContours() {
|
|
||||||
if (this.m_cachedContours) return this.m_cachedContours;
|
toContoursImpl() {
|
||||||
const expandResult = this.expand();
|
const expandResult = this.expand();
|
||||||
const lhs = [...expandResult.lhsUntransformed];
|
const lhs = [...expandResult.lhsUntransformed];
|
||||||
const rhs = [...expandResult.rhsUntransformed];
|
const rhs = [...expandResult.rhsUntransformed];
|
||||||
|
@ -134,23 +161,20 @@ export class DiSpiroGeometry extends GeometryBase {
|
||||||
for (const k of rhs) k.reverseType();
|
for (const k of rhs) k.reverseType();
|
||||||
rhs.reverse();
|
rhs.reverse();
|
||||||
|
|
||||||
let outlineGeometry;
|
|
||||||
if (this.m_closed) {
|
if (this.m_closed) {
|
||||||
outlineGeometry = new CombineGeometry([
|
return [
|
||||||
new SpiroGeometry(this.m_gizmo, true, lhs),
|
...new SpiroGeometry(this.m_gizmo, true, lhs).toContoursImpl(),
|
||||||
new SpiroGeometry(this.m_gizmo, true, rhs),
|
...new SpiroGeometry(this.m_gizmo, true, rhs).toContoursImpl(),
|
||||||
]);
|
];
|
||||||
} else {
|
} else {
|
||||||
lhs[0].type = lhs[lhs.length - 1].type = "corner";
|
lhs[0].type = lhs[lhs.length - 1].type = "corner";
|
||||||
rhs[0].type = rhs[rhs.length - 1].type = "corner";
|
rhs[0].type = rhs[rhs.length - 1].type = "corner";
|
||||||
const allKnots = lhs.concat(rhs);
|
const allKnots = lhs.concat(rhs);
|
||||||
outlineGeometry = new SpiroGeometry(this.m_gizmo, true, allKnots);
|
return new SpiroGeometry(this.m_gizmo, true, allKnots).toContoursImpl();
|
||||||
}
|
}
|
||||||
this.m_cachedContours = outlineGeometry.toContours();
|
|
||||||
return this.m_cachedContours;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
expand() {
|
expand() {
|
||||||
if (this.m_cachedExpansionResults) return this.m_cachedExpansionResults;
|
|
||||||
const expander = new SpiroExpander(
|
const expander = new SpiroExpander(
|
||||||
this.m_gizmo,
|
this.m_gizmo,
|
||||||
this.m_contrast,
|
this.m_contrast,
|
||||||
|
@ -162,8 +186,7 @@ export class DiSpiroGeometry extends GeometryBase {
|
||||||
expander.iterateNormals();
|
expander.iterateNormals();
|
||||||
expander.iterateNormals();
|
expander.iterateNormals();
|
||||||
expander.iterateNormals();
|
expander.iterateNormals();
|
||||||
this.m_cachedExpansionResults = expander.expand();
|
return expander.expand();
|
||||||
return this.m_cachedExpansionResults;
|
|
||||||
}
|
}
|
||||||
toReferences() {
|
toReferences() {
|
||||||
return null;
|
return null;
|
||||||
|
@ -181,14 +204,16 @@ export class DiSpiroGeometry extends GeometryBase {
|
||||||
}
|
}
|
||||||
return cplx;
|
return cplx;
|
||||||
}
|
}
|
||||||
toShapeStringOrNull() {
|
|
||||||
return Format.struct(
|
hash(h) {
|
||||||
"DiSpiroGeometry",
|
h.beginStruct("DiSpiroGeometry");
|
||||||
Format.gizmo(this.m_gizmo),
|
h.gizmo(this.m_gizmo);
|
||||||
Format.n(this.m_contrast),
|
h.f64(this.m_contrast);
|
||||||
this.m_closed,
|
h.bool(this.m_closed);
|
||||||
Format.list(this.m_biKnots.map(z => z.toShapeString())),
|
h.beginArray(this.m_biKnots.length);
|
||||||
);
|
for (const knot of this.m_biKnots) h.embed(knot);
|
||||||
|
h.endArray();
|
||||||
|
h.endStruct();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -206,8 +231,8 @@ export class ReferenceGeometry extends GeometryBase {
|
||||||
this.m_glyph.geometry,
|
this.m_glyph.geometry,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
toContours() {
|
toContours(ctx) {
|
||||||
return this.unwrap().toContours();
|
return this.unwrap().toContours(ctx);
|
||||||
}
|
}
|
||||||
toReferences() {
|
toReferences() {
|
||||||
if (this.m_glyph.geometry.measureComplexity() & CPLX_NON_EMPTY) {
|
if (this.m_glyph.geometry.measureComplexity() & CPLX_NON_EMPTY) {
|
||||||
|
@ -229,10 +254,13 @@ export class ReferenceGeometry extends GeometryBase {
|
||||||
unlinkReferences() {
|
unlinkReferences() {
|
||||||
return this.unwrap().unlinkReferences();
|
return this.unwrap().unlinkReferences();
|
||||||
}
|
}
|
||||||
toShapeStringOrNull() {
|
|
||||||
let sTarget = this.m_glyph.geometry.toShapeStringOrNull();
|
hash(h) {
|
||||||
if (!sTarget) return null;
|
h.beginStruct("ReferenceGeometry");
|
||||||
return Format.struct("ReferenceGeometry", sTarget, Format.n(this.m_x), Format.n(this.m_y));
|
h.embed(this.m_glyph.geometry);
|
||||||
|
h.f64(this.m_x);
|
||||||
|
h.f64(this.m_y);
|
||||||
|
h.endStruct();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -242,8 +270,8 @@ export class TaggedGeometry extends GeometryBase {
|
||||||
this.m_geom = g;
|
this.m_geom = g;
|
||||||
this.m_tag = tag;
|
this.m_tag = tag;
|
||||||
}
|
}
|
||||||
toContours() {
|
toContours(ctx) {
|
||||||
return this.m_geom.toContours();
|
return this.m_geom.toContours(ctx);
|
||||||
}
|
}
|
||||||
toReferences() {
|
toReferences() {
|
||||||
return this.m_geom.toReferences();
|
return this.m_geom.toReferences();
|
||||||
|
@ -261,8 +289,9 @@ export class TaggedGeometry extends GeometryBase {
|
||||||
unlinkReferences() {
|
unlinkReferences() {
|
||||||
return this.m_geom.unlinkReferences();
|
return this.m_geom.unlinkReferences();
|
||||||
}
|
}
|
||||||
toShapeStringOrNull() {
|
|
||||||
return this.m_geom.toShapeStringOrNull();
|
hash(h) {
|
||||||
|
this.m_geom.hash(h);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -277,9 +306,9 @@ export class TransformedGeometry extends GeometryBase {
|
||||||
return new TransformedGeometry(Transform.Combine(this.m_transform, tfm), this.m_geom);
|
return new TransformedGeometry(Transform.Combine(this.m_transform, tfm), this.m_geom);
|
||||||
}
|
}
|
||||||
|
|
||||||
toContours() {
|
toContours(ctx) {
|
||||||
let result = [];
|
let result = [];
|
||||||
for (const c of this.m_geom.toContours()) {
|
for (const c of this.m_geom.toContours(ctx)) {
|
||||||
let c1 = [];
|
let c1 = [];
|
||||||
for (const z of c) c1.push(Point.transformed(this.m_transform, z));
|
for (const z of c) c1.push(Point.transformed(this.m_transform, z));
|
||||||
result.push(c1);
|
result.push(c1);
|
||||||
|
@ -319,10 +348,13 @@ export class TransformedGeometry extends GeometryBase {
|
||||||
return new TransformedGeometry(this.m_transform, unwrapped);
|
return new TransformedGeometry(this.m_transform, unwrapped);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
toShapeStringOrNull() {
|
|
||||||
const sTarget = this.m_geom.toShapeStringOrNull();
|
hash(h) {
|
||||||
if (!sTarget) return null;
|
h.beginStruct("TransformedGeometry");
|
||||||
return Format.struct("TransformedGeometry", Format.gizmo(this.m_transform), sTarget);
|
h.gizmo(this.m_transform);
|
||||||
|
h.embed(this.m_geom);
|
||||||
|
h.endStruct();
|
||||||
|
return h;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -331,8 +363,8 @@ export class RadicalGeometry extends GeometryBase {
|
||||||
super();
|
super();
|
||||||
this.m_geom = g;
|
this.m_geom = g;
|
||||||
}
|
}
|
||||||
toContours() {
|
toContours(ctx) {
|
||||||
return this.m_geom.toContours();
|
return this.m_geom.toContours(ctx);
|
||||||
}
|
}
|
||||||
toReferences() {
|
toReferences() {
|
||||||
return null;
|
return null;
|
||||||
|
@ -351,10 +383,9 @@ export class RadicalGeometry extends GeometryBase {
|
||||||
unlinkReferences() {
|
unlinkReferences() {
|
||||||
return this.m_geom.unlinkReferences();
|
return this.m_geom.unlinkReferences();
|
||||||
}
|
}
|
||||||
toShapeStringOrNull() {
|
|
||||||
const sTarget = this.m_geom.toShapeStringOrNull();
|
hash(h) {
|
||||||
if (!sTarget) return null;
|
this.m_geom.hash(h);
|
||||||
return Format.struct("RadicalGeometry", sTarget);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -370,10 +401,10 @@ export class CombineGeometry extends GeometryBase {
|
||||||
return new CombineGeometry([...this.m_parts, g]);
|
return new CombineGeometry([...this.m_parts, g]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
toContours() {
|
toContours(ctx) {
|
||||||
let results = [];
|
let results = [];
|
||||||
for (const part of this.m_parts) {
|
for (const part of this.m_parts) {
|
||||||
for (const c of part.toContours()) {
|
for (const c of part.toContours(ctx)) {
|
||||||
results.push(c);
|
results.push(c);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -424,30 +455,24 @@ export class CombineGeometry extends GeometryBase {
|
||||||
}
|
}
|
||||||
return new CombineGeometry(parts);
|
return new CombineGeometry(parts);
|
||||||
}
|
}
|
||||||
toShapeStringOrNull() {
|
|
||||||
let sParts = [];
|
hash(h) {
|
||||||
for (const item of this.m_parts) {
|
h.beginStruct("CombineGeometry");
|
||||||
const sPart = item.toShapeStringOrNull();
|
h.beginArray(this.m_parts.length);
|
||||||
if (!sPart) return null;
|
for (const part of this.m_parts) h.embed(part);
|
||||||
sParts.push(sPart);
|
h.endArray();
|
||||||
}
|
h.endStruct();
|
||||||
return Format.struct("CombineGeometry", Format.list(sParts));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export class BooleanGeometry extends GeometryBase {
|
export class BooleanGeometry extends CachedGeometry {
|
||||||
constructor(operator, operands) {
|
constructor(operator, operands) {
|
||||||
super();
|
super();
|
||||||
this.m_operator = operator;
|
this.m_operator = operator;
|
||||||
this.m_operands = operands;
|
this.m_operands = operands;
|
||||||
this.m_resolved = null;
|
|
||||||
}
|
}
|
||||||
toContours() {
|
|
||||||
if (this.m_resolved) return this.m_resolved;
|
toContoursImpl() {
|
||||||
this.m_resolved = this.asContoursImpl();
|
|
||||||
return this.m_resolved;
|
|
||||||
}
|
|
||||||
asContoursImpl() {
|
|
||||||
if (this.m_operands.length === 0) return [];
|
if (this.m_operands.length === 0) return [];
|
||||||
|
|
||||||
const stack = [];
|
const stack = [];
|
||||||
|
@ -516,18 +541,18 @@ export class BooleanGeometry extends GeometryBase {
|
||||||
}
|
}
|
||||||
return new BooleanGeometry(this.m_operator, operands);
|
return new BooleanGeometry(this.m_operator, operands);
|
||||||
}
|
}
|
||||||
toShapeStringOrNull() {
|
|
||||||
let sParts = [];
|
hash(h) {
|
||||||
for (const item of this.m_operands) {
|
h.beginStruct("BooleanGeometry");
|
||||||
const sPart = item.toShapeStringOrNull();
|
h.u32(this.m_operator);
|
||||||
if (!sPart) return null;
|
h.beginArray(this.m_operands.length);
|
||||||
sParts.push(sPart);
|
for (const operand of this.m_operands) h.embed(operand);
|
||||||
}
|
h.endArray();
|
||||||
return Format.struct("BooleanGeometry", this.m_operator, Format.list(sParts));
|
h.endStruct();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export class StrokeGeometry extends GeometryBase {
|
export class StrokeGeometry extends CachedGeometry {
|
||||||
constructor(geom, gizmo, radius, contrast, fInside) {
|
constructor(geom, gizmo, radius, contrast, fInside) {
|
||||||
super();
|
super();
|
||||||
this.m_geom = geom;
|
this.m_geom = geom;
|
||||||
|
@ -537,11 +562,11 @@ export class StrokeGeometry extends GeometryBase {
|
||||||
this.m_fInside = fInside;
|
this.m_fInside = fInside;
|
||||||
}
|
}
|
||||||
|
|
||||||
toContours() {
|
toContoursImpl(ctx) {
|
||||||
// Produce simplified arcs
|
// Produce simplified arcs
|
||||||
const nonTransformedGeometry = new TransformedGeometry(this.m_gizmo.inverse(), this.m_geom);
|
const nonTransformedGeometry = new TransformedGeometry(this.m_gizmo.inverse(), this.m_geom);
|
||||||
let arcs = TypoGeom.Boolean.removeOverlap(
|
let arcs = TypoGeom.Boolean.removeOverlap(
|
||||||
CurveUtil.convertShapeToArcs(nonTransformedGeometry.toContours()),
|
CurveUtil.convertShapeToArcs(nonTransformedGeometry.toContours(ctx)),
|
||||||
TypoGeom.Boolean.PolyFillType.pftNonZero,
|
TypoGeom.Boolean.PolyFillType.pftNonZero,
|
||||||
CurveUtil.BOOLE_RESOLUTION,
|
CurveUtil.BOOLE_RESOLUTION,
|
||||||
);
|
);
|
||||||
|
@ -590,29 +615,27 @@ export class StrokeGeometry extends GeometryBase {
|
||||||
measureComplexity() {
|
measureComplexity() {
|
||||||
return this.m_geom.measureComplexity() | CPLX_NON_SIMPLE;
|
return this.m_geom.measureComplexity() | CPLX_NON_SIMPLE;
|
||||||
}
|
}
|
||||||
toShapeStringOrNull() {
|
|
||||||
const sTarget = this.m_geom.unlinkReferences().toShapeStringOrNull();
|
hash(h) {
|
||||||
if (!sTarget) return null;
|
h.beginStruct("StrokeGeometry");
|
||||||
return Format.struct(
|
h.embed(this.m_geom);
|
||||||
`StrokeGeometry`,
|
h.gizmo(this.m_gizmo);
|
||||||
sTarget,
|
h.f64(this.m_radius);
|
||||||
Format.gizmo(this.m_gizmo),
|
h.f64(this.m_contrast);
|
||||||
Format.n(this.m_radius),
|
h.bool(this.m_fInside);
|
||||||
Format.n(this.m_contrast),
|
h.endStruct();
|
||||||
this.m_fInside,
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// This special geometry type is used in the finalization phase to create TTF contours.
|
// This special geometry type is used in the finalization phase to create TTF contours.
|
||||||
export class SimplifyGeometry extends GeometryBase {
|
export class SimplifyGeometry extends CachedGeometry {
|
||||||
constructor(g) {
|
constructor(g) {
|
||||||
super();
|
super();
|
||||||
this.m_geom = g;
|
this.m_geom = g;
|
||||||
}
|
}
|
||||||
toContours() {
|
toContoursImpl(ctx) {
|
||||||
// Produce simplified arcs
|
// Produce simplified arcs
|
||||||
let arcs = CurveUtil.convertShapeToArcs(this.m_geom.toContours());
|
let arcs = CurveUtil.convertShapeToArcs(this.m_geom.toContours(ctx));
|
||||||
if (this.m_geom.measureComplexity() & CPLX_NON_SIMPLE) {
|
if (this.m_geom.measureComplexity() & CPLX_NON_SIMPLE) {
|
||||||
arcs = TypoGeom.Boolean.removeOverlap(
|
arcs = TypoGeom.Boolean.removeOverlap(
|
||||||
arcs,
|
arcs,
|
||||||
|
@ -645,10 +668,11 @@ export class SimplifyGeometry extends GeometryBase {
|
||||||
measureComplexity() {
|
measureComplexity() {
|
||||||
return this.m_geom.measureComplexity();
|
return this.m_geom.measureComplexity();
|
||||||
}
|
}
|
||||||
toShapeStringOrNull() {
|
|
||||||
const sTarget = this.m_geom.unlinkReferences().toShapeStringOrNull();
|
hash(h) {
|
||||||
if (!sTarget) return null;
|
h.beginStruct("SimplifyGeometry");
|
||||||
return `SimplifyGeometry{${sTarget}}`;
|
h.embed(this.m_geom);
|
||||||
|
h.endStruct();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -662,7 +686,7 @@ export function combineWith(a, b) {
|
||||||
}
|
}
|
||||||
|
|
||||||
export function hashGeometry(geom) {
|
export function hashGeometry(geom) {
|
||||||
const s = geom.toShapeStringOrNull();
|
const hasher = new Format.Hasher();
|
||||||
if (!s) return null;
|
geom.hash(hasher);
|
||||||
return crypto.createHash("sha256").update(s).digest("hex");
|
return hasher.digest();
|
||||||
}
|
}
|
||||||
|
|
|
@ -115,9 +115,15 @@ export class MonoKnot {
|
||||||
const k1 = new MonoKnot(this.type, this.x, this.y, this.unimportant);
|
const k1 = new MonoKnot(this.type, this.x, this.y, this.unimportant);
|
||||||
return k1;
|
return k1;
|
||||||
}
|
}
|
||||||
toShapeString() {
|
hash(h) {
|
||||||
return Format.tuple(this.type, this.unimportant, Format.n(this.x), Format.n(this.y));
|
h.beginStruct("MonoKnot");
|
||||||
|
h.str(this.type);
|
||||||
|
h.bool(this.unimportant);
|
||||||
|
h.f64(this.x);
|
||||||
|
h.f64(this.y);
|
||||||
|
h.endStruct();
|
||||||
}
|
}
|
||||||
|
|
||||||
reverseType() {
|
reverseType() {
|
||||||
if (this.type === "left") {
|
if (this.type === "left") {
|
||||||
this.type = "right";
|
this.type = "right";
|
||||||
|
@ -158,19 +164,26 @@ class BiKnot {
|
||||||
k1.unimportant = this.unimportant;
|
k1.unimportant = this.unimportant;
|
||||||
return k1;
|
return k1;
|
||||||
}
|
}
|
||||||
toShapeString() {
|
hash(h) {
|
||||||
return Format.tuple(
|
h.beginStruct("BiKnot");
|
||||||
this.type,
|
h.str(this.type);
|
||||||
this.unimportant,
|
h.bool(this.unimportant);
|
||||||
Format.n(this.x),
|
h.f64(this.x);
|
||||||
Format.n(this.y),
|
h.f64(this.y);
|
||||||
this.d1 == null ? "" : Format.n(this.d1),
|
|
||||||
this.d2 == null ? "" : Format.n(this.d2),
|
h.bool(this.d1 != null);
|
||||||
this.proposedNormal
|
if (this.d1 != null) h.f64(this.d1);
|
||||||
? Format.tuple(Format.n(this.proposedNormal.x), Format.n(this.proposedNormal.y))
|
h.bool(this.d2 != null);
|
||||||
: "",
|
if (this.d2 != null) h.f64(this.d2);
|
||||||
);
|
|
||||||
|
h.bool(this.proposedNormal != null);
|
||||||
|
if (this.proposedNormal) {
|
||||||
|
h.f64(this.proposedNormal.x);
|
||||||
|
h.f64(this.proposedNormal.y);
|
||||||
}
|
}
|
||||||
|
h.endStruct();
|
||||||
|
}
|
||||||
|
|
||||||
toMono() {
|
toMono() {
|
||||||
return new MonoKnot(this.type, this.unimportant, this.x, this.y);
|
return new MonoKnot(this.type, this.unimportant, this.x, this.y);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
{
|
{
|
||||||
"name": "@iosevka/glyph",
|
"name": "@iosevka/glyph",
|
||||||
"version": "29.0.5",
|
"version": "29.0.6",
|
||||||
"private": true,
|
"private": true,
|
||||||
"exports": {
|
"exports": {
|
||||||
".": "./src/glyph.mjs",
|
".": "./src/glyph.mjs",
|
||||||
|
@ -9,6 +9,6 @@
|
||||||
"./relation": "./src/relation.mjs"
|
"./relation": "./src/relation.mjs"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@iosevka/geometry": "29.0.5"
|
"@iosevka/geometry": "29.0.6"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -150,8 +150,8 @@ export class Glyph {
|
||||||
tryBecomeMirrorOf(dst, rankSet) {
|
tryBecomeMirrorOf(dst, rankSet) {
|
||||||
if (rankSet.has(this) || rankSet.has(dst)) return;
|
if (rankSet.has(this) || rankSet.has(dst)) return;
|
||||||
if (dst.hasDependency(this)) return;
|
if (dst.hasDependency(this)) return;
|
||||||
const csThis = this.geometry.unlinkReferences().toShapeStringOrNull();
|
const csThis = Geom.hashGeometry(this.geometry.unlinkReferences());
|
||||||
const csDst = dst.geometry.unlinkReferences().toShapeStringOrNull();
|
const csDst = Geom.hashGeometry(dst.geometry.unlinkReferences());
|
||||||
if (csThis && csDst && csThis === csDst) {
|
if (csThis && csDst && csThis === csDst) {
|
||||||
this.geometry = new Geom.CombineGeometry([new Geom.ReferenceGeometry(dst, 0, 0)]);
|
this.geometry = new Geom.CombineGeometry([new Geom.ReferenceGeometry(dst, 0, 0)]);
|
||||||
rankSet.add(this);
|
rankSet.add(this);
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
{
|
{
|
||||||
"name": "@iosevka/param",
|
"name": "@iosevka/param",
|
||||||
"version": "29.0.5",
|
"version": "29.0.6",
|
||||||
"private": true,
|
"private": true,
|
||||||
"exports": {
|
"exports": {
|
||||||
".": "./src/index.mjs",
|
".": "./src/index.mjs",
|
||||||
|
@ -9,6 +9,6 @@
|
||||||
"./metric-override": "./src/metric-override.mjs"
|
"./metric-override": "./src/metric-override.mjs"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@iosevka/util": "29.0.5"
|
"@iosevka/util": "29.0.6"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
{
|
{
|
||||||
"name": "@iosevka/util",
|
"name": "@iosevka/util",
|
||||||
"version": "29.0.5",
|
"version": "29.0.6",
|
||||||
"private": true,
|
"private": true,
|
||||||
"exports": {
|
"exports": {
|
||||||
".": "./src/index.mjs",
|
".": "./src/index.mjs",
|
||||||
|
|
|
@ -1,18 +1,108 @@
|
||||||
export function struct(leader, ...items) {
|
import crypto from "crypto";
|
||||||
return "" + leader + "(" + items.join(";") + ")";
|
|
||||||
}
|
const TAG_INVALID = 0x11000000;
|
||||||
export function tuple(...items) {
|
const TAG_BEGIN_STRUCT = 0x12340001;
|
||||||
return "(" + items.join(";") + ")";
|
const TAG_END_STRUCT = 0x12340002;
|
||||||
}
|
const TAG_BEGIN_ARRAY = 0x12340003;
|
||||||
export function list(items) {
|
const TAG_END_ARRAY = 0x12340004;
|
||||||
return "{" + items.join(";") + "}";
|
const TAG_BEGIN_STR = 0x12340005;
|
||||||
}
|
const TAG_END_STR = 0x12340006;
|
||||||
export function n(x) {
|
const TAG_BEGIN_STRUCT_TYPE = 0x12340007;
|
||||||
return String(Math.round(x * 0x10000));
|
const TAG_END_STRUCT_TYPE = 0x12340008;
|
||||||
}
|
|
||||||
export function typedPoint(z) {
|
const TAG_TYPED_POINT = 0x12340010;
|
||||||
return tuple(z.type, n(z.x), n(z.y));
|
const TAG_GIZMO = 0x12340011;
|
||||||
}
|
const TAG_LIST_LENGTH = 0x12340012;
|
||||||
export function gizmo(g) {
|
|
||||||
return tuple(n(g.xx), n(g.xy), n(g.yx), n(g.yy), n(g.tx), n(g.ty));
|
const TAG_EMBED_BEGIN = 0x12340020;
|
||||||
|
const TAG_EMBED_END = 0x12340021;
|
||||||
|
|
||||||
|
export class Hasher {
|
||||||
|
constructor() {
|
||||||
|
this.hash = crypto.createHash("sha256");
|
||||||
|
this.buf4 = Buffer.alloc(4);
|
||||||
|
this.buf8 = Buffer.alloc(8);
|
||||||
|
}
|
||||||
|
|
||||||
|
digest() {
|
||||||
|
return this.hash.digest("hex");
|
||||||
|
}
|
||||||
|
|
||||||
|
invalid() {
|
||||||
|
this.u32(TAG_INVALID);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
beginStruct(typeStr) {
|
||||||
|
this.u32(TAG_BEGIN_STRUCT);
|
||||||
|
if (typeStr) {
|
||||||
|
this.u32(TAG_BEGIN_STRUCT_TYPE);
|
||||||
|
this.hash.update(typeStr);
|
||||||
|
this.u32(TAG_END_STRUCT_TYPE);
|
||||||
|
}
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
endStruct() {
|
||||||
|
this.u32(TAG_END_STRUCT);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
beginArray(n) {
|
||||||
|
this.u32(TAG_BEGIN_ARRAY);
|
||||||
|
this.u32(TAG_LIST_LENGTH);
|
||||||
|
this.u32(n);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
endArray() {
|
||||||
|
this.u32(TAG_END_ARRAY);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
str(s) {
|
||||||
|
this.u32(TAG_BEGIN_STR);
|
||||||
|
this.hash.update(s);
|
||||||
|
this.u32(TAG_END_STR);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
embed(other) {
|
||||||
|
this.u32(TAG_EMBED_BEGIN);
|
||||||
|
other.hash(this);
|
||||||
|
this.u32(TAG_EMBED_END);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool(x) {
|
||||||
|
this.u32(x ? 1 : 0);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
u32(x) {
|
||||||
|
this.buf4.writeUInt32LE(x, 0);
|
||||||
|
this.hash.update(this.buf4);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
i32(x) {
|
||||||
|
this.buf4.writeInt32LE(x, 0);
|
||||||
|
this.hash.update(this.buf4);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
f64(x) {
|
||||||
|
this.buf8.writeDoubleLE(x, 0);
|
||||||
|
this.hash.update(this.buf8);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
typedPoint(z) {
|
||||||
|
this.u32(TAG_TYPED_POINT);
|
||||||
|
this.u32(z.type);
|
||||||
|
this.f64(z.x);
|
||||||
|
this.f64(z.y);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
gizmo(g) {
|
||||||
|
this.u32(TAG_GIZMO);
|
||||||
|
this.f64(g.xx);
|
||||||
|
this.f64(g.xy);
|
||||||
|
this.f64(g.yx);
|
||||||
|
this.f64(g.yy);
|
||||||
|
this.f64(g.tx);
|
||||||
|
this.f64(g.ty);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,13 +1,13 @@
|
||||||
{
|
{
|
||||||
"name": "@iosevka/amend-readme",
|
"name": "@iosevka/amend-readme",
|
||||||
"version": "29.0.5",
|
"version": "29.0.6",
|
||||||
"private": true,
|
"private": true,
|
||||||
"exports": {
|
"exports": {
|
||||||
".": "./src/index.mjs"
|
".": "./src/index.mjs"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@iarna/toml": "^2.2.5",
|
"@iarna/toml": "^2.2.5",
|
||||||
"@iosevka/param": "29.0.5",
|
"@iosevka/param": "29.0.6",
|
||||||
"@unicode/unicode-15.1.0": "^1.5.2"
|
"@unicode/unicode-15.1.0": "^1.5.2"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
{
|
{
|
||||||
"name": "@iosevka/data-export",
|
"name": "@iosevka/data-export",
|
||||||
"version": "29.0.5",
|
"version": "29.0.6",
|
||||||
"private": true,
|
"private": true,
|
||||||
"exports": {
|
"exports": {
|
||||||
".": "./src/index.mjs",
|
".": "./src/index.mjs",
|
||||||
|
@ -10,7 +10,7 @@
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@iarna/toml": "^2.2.5",
|
"@iarna/toml": "^2.2.5",
|
||||||
"@iosevka/param": "29.0.5",
|
"@iosevka/param": "29.0.6",
|
||||||
"@unicode/unicode-15.1.0": "^1.5.2",
|
"@unicode/unicode-15.1.0": "^1.5.2",
|
||||||
"cldr": "^7.5.0"
|
"cldr": "^7.5.0"
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,11 +1,11 @@
|
||||||
{
|
{
|
||||||
"name": "@iosevka/generate-samples",
|
"name": "@iosevka/generate-samples",
|
||||||
"version": "29.0.5",
|
"version": "29.0.6",
|
||||||
"private": true,
|
"private": true,
|
||||||
"exports": {
|
"exports": {
|
||||||
".": "./src/index.mjs"
|
".": "./src/index.mjs"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@iosevka/data-export": "29.0.5"
|
"@iosevka/data-export": "29.0.6"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,10 +1,10 @@
|
||||||
{
|
{
|
||||||
"name": "@iosevka/misc",
|
"name": "@iosevka/misc",
|
||||||
"version": "29.0.5",
|
"version": "29.0.6",
|
||||||
"private": true,
|
"private": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"semver": "^7.6.0",
|
"semver": "^7.6.0",
|
||||||
"wawoff2": "^2.0.1",
|
"wawoff2": "^2.0.1",
|
||||||
"@iosevka/util": "29.0.5"
|
"@iosevka/util": "29.0.6"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue