diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 01866976..c693b690 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -1,10 +1,15 @@ repos: # Standard file hygiene + # Generated files (ts-rs output, NAPI .d.ts, parity fixtures) are excluded + # because their format is owned by the generator. Re-formatting them here + # creates a loop with the cargo-test hook that regenerates them. - repo: https://github.com/pre-commit/pre-commit-hooks rev: v5.0.0 hooks: - id: trailing-whitespace + exclude: '^(packages/types/src/generated/|packages/types/__fixtures__/|crates/shift-node/index\.(d\.ts|js))' - id: end-of-file-fixer + exclude: '^(packages/types/src/generated/|packages/types/__fixtures__/|crates/shift-node/index\.(d\.ts|js))' - id: check-yaml - id: check-added-large-files - id: check-merge-conflict @@ -20,7 +25,7 @@ repos: - id: no-console-log name: no console.log in production code - entry: "bash -c 'for f in \"$@\"; do case \"$f\" in *.test.*|*/testing/*|*/e2e/*) continue;; esac; if grep -n \"^\\s*console\\.log\\b\" \"$f\" >/dev/null 2>&1; then echo \"$f has console.log:\"; grep -n \"^\\s*console\\.log\\b\" \"$f\"; exit 1; fi; done'" + entry: "bash -c 'for f in \"$@\"; do case \"$f\" in *.test.*|*/testing/*|*/e2e/*|scripts/*) continue;; esac; if grep -n \"^\\s*console\\.log\\b\" \"$f\" >/dev/null 2>&1; then echo \"$f has console.log:\"; grep -n \"^\\s*console\\.log\\b\" \"$f\"; exit 1; fi; done'" language: system types_or: [javascript, jsx, ts, tsx] diff --git a/.prettierignore b/.prettierignore index 511de71c..a8a5b92b 100644 --- a/.prettierignore +++ b/.prettierignore @@ -6,6 +6,7 @@ out *.min.css pnpm-lock.yaml packages/types/src/generated +packages/types/__fixtures__ crates/shift-node/index.js crates/shift-node/index.d.ts **/vendor diff --git a/Cargo.lock b/Cargo.lock index 8b7bddc7..2541747c 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -138,6 +138,16 @@ version = "2.9.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1b8e56985ec62d17e9c1001dc89c88ecd7dc08e47eba5ec7c29c7b5eeecde967" +[[package]] +name = "borsh" +version = "1.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cfd1e3f8955a5d7de9fab72fc8373fade9fb8a703968cb200ae3dc6cf08e185a" +dependencies = [ + "bytes", + "cfg_aliases", +] + [[package]] name = "bumpalo" version = "3.19.0" @@ -164,6 +174,12 @@ dependencies = [ "syn", ] +[[package]] +name = "bytes" +version = "1.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e748733b7cbc798e1434b6ac524f0c1ff2ab456fe201501e6497c8417a4fc33" + [[package]] name = "camino" version = "1.1.10" @@ -211,6 +227,12 @@ version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9555578bc9e57714c812a1f84e4fc5b4d21fcb063490c624de019f7464c91268" +[[package]] +name = "cfg_aliases" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "613afe47fcd5fac7ccf1db93babcb082c5994d996f20b8b159f2ad1658eb5724" + [[package]] name = "chrono" version = "0.4.41" @@ -517,14 +539,14 @@ dependencies = [ "ansi_term", "chrono", "env_logger", - "fontdrasil", + "fontdrasil 0.2.0", "indexmap", "log", - "ordered-float", + "ordered-float 4.6.0", "serde", - "smol_str", + "smol_str 0.2.2", "thiserror 1.0.69", - "write-fonts", + "write-fonts 0.38.2", ] [[package]] @@ -555,6 +577,16 @@ dependencies = [ "serde", ] +[[package]] +name = "font-types" +version = "0.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "39a654f404bbcbd48ea58c617c2993ee91d1cb63727a37bf2323a4edeed1b8c5" +dependencies = [ + "bytemuck", + "serde", +] + [[package]] name = "fontbe" version = "0.2.0" @@ -565,19 +597,19 @@ dependencies = [ "chrono", "env_logger", "fea-rs", - "fontdrasil", + "fontdrasil 0.2.0", "fontir", "icu_properties", "indexmap", "kurbo 0.11.2", "log", - "ordered-float", + "ordered-float 4.6.0", "parking_lot", "serde", - "smol_str", + "smol_str 0.2.2", "thiserror 1.0.69", "tinystr", - "write-fonts", + "write-fonts 0.38.2", ] [[package]] @@ -593,7 +625,7 @@ dependencies = [ "env_logger", "filetime", "fontbe", - "fontdrasil", + "fontdrasil 0.2.0", "fontir", "fontra2fontir", "glyphs2fontir", @@ -606,7 +638,7 @@ dependencies = [ "thiserror 1.0.69", "ufo2fontir", "vergen-gitcl", - "write-fonts", + "write-fonts 0.38.2", ] [[package]] @@ -615,10 +647,26 @@ version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a7486f5a01d9b86a45a53e4d2f46172d731af11e801a3c7c24af30cab055b9d0" dependencies = [ - "ordered-float", + "ordered-float 4.6.0", "serde", - "smol_str", - "write-fonts", + "smol_str 0.2.2", + "write-fonts 0.38.2", +] + +[[package]] +name = "fontdrasil" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fa3a7a2fbc9d1817cd07298326376c8bd39868efe7c6149090c4fafea95eaf34" +dependencies = [ + "env_logger", + "kurbo 0.12.0", + "log", + "ordered-float 5.3.0", + "serde", + "smol_str 0.3.6", + "thiserror 2.0.12", + "write-fonts 0.44.1", ] [[package]] @@ -632,17 +680,17 @@ dependencies = [ "chrono", "env_logger", "filetime", - "fontdrasil", + "fontdrasil 0.2.0", "indexmap", "kurbo 0.11.2", "log", - "ordered-float", + "ordered-float 4.6.0", "parking_lot", "serde", "serde_yaml", - "smol_str", + "smol_str 0.2.2", "thiserror 1.0.69", - "write-fonts", + "write-fonts 0.38.2", ] [[package]] @@ -652,16 +700,16 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4511cace96f3243fef1350e87abf326900ce3a7af6c3646e7cb6e3b26b295baf" dependencies = [ "env_logger", - "fontdrasil", + "fontdrasil 0.2.0", "fontir", "indexmap", "kurbo 0.11.2", "log", - "ordered-float", + "ordered-float 4.6.0", "serde", "serde_json", "thiserror 1.0.69", - "write-fonts", + "write-fonts 0.38.2", ] [[package]] @@ -774,16 +822,16 @@ dependencies = [ "bincode", "chrono", "env_logger", - "fontdrasil", + "fontdrasil 0.2.0", "icu_properties", "indexmap", "kurbo 0.11.2", "log", - "ordered-float", + "ordered-float 4.6.0", "quick-xml", "regex", "serde", - "smol_str", + "smol_str 0.2.2", "thiserror 1.0.69", ] @@ -795,16 +843,16 @@ checksum = "d66204b6a2d374b221a9676b22b64de7a711482dc58f6a13da1c4b20978a3d43" dependencies = [ "chrono", "env_logger", - "fontdrasil", + "fontdrasil 0.2.0", "fontir", "glyphs-reader", "indexmap", "kurbo 0.11.2", "log", - "ordered-float", - "smol_str", + "ordered-float 4.6.0", + "smol_str 0.2.2", "thiserror 1.0.69", - "write-fonts", + "write-fonts 0.38.2", ] [[package]] @@ -988,6 +1036,18 @@ dependencies = [ "smallvec", ] +[[package]] +name = "kurbo" +version = "0.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ce9729cc38c18d86123ab736fd2e7151763ba226ac2490ec092d1dd148825e32" +dependencies = [ + "arrayvec", + "euclid", + "serde", + "smallvec", +] + [[package]] name = "kurbo" version = "0.13.0" @@ -1235,6 +1295,17 @@ dependencies = [ "serde", ] +[[package]] +name = "ordered-float" +version = "5.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b7d950ca161dc355eaf28f82b11345ed76c6e1f6eb1f4f4479e0323b9e2fbd0e" +dependencies = [ + "num-traits", + "rand", + "serde", +] + [[package]] name = "parking_lot" version = "0.12.4" @@ -1396,7 +1467,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "04ca636dac446b5664bd16c069c00a9621806895b8bb02c2dc68542b23b8f25d" dependencies = [ "bytemuck", - "font-types", + "font-types 0.9.0", "serde", ] @@ -1407,7 +1478,18 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "192735ef611aac958468e670cb98432c925426f3cb71521fda202130f7388d91" dependencies = [ "bytemuck", - "font-types", + "font-types 0.9.0", +] + +[[package]] +name = "read-fonts" +version = "0.36.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5eaa2941a4c05443ee3a7b26ab076a553c343ad5995230cc2b1d3e993bdc6345" +dependencies = [ + "bytemuck", + "font-types 0.10.1", + "serde", ] [[package]] @@ -1587,6 +1669,7 @@ version = "0.0.0" dependencies = [ "bitflags", "fontc", + "fontdrasil 0.4.0", "norad 0.16.0", "serde", "serde_json", @@ -1601,6 +1684,8 @@ dependencies = [ name = "shift-ir" version = "0.1.0" dependencies = [ + "fontdrasil 0.4.0", + "indexmap", "kurbo 0.13.0", "linesweeper", "serde", @@ -1659,6 +1744,16 @@ dependencies = [ "serde", ] +[[package]] +name = "smol_str" +version = "0.3.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4aaa7368fcf4852a4c2dd92df0cace6a71f2091ca0a23391ce7f3a31833f1523" +dependencies = [ + "borsh", + "serde_core", +] + [[package]] name = "stable_deref_trait" version = "1.2.0" @@ -1838,18 +1933,18 @@ checksum = "6d6a943c02f505748a2d076447518ef08fdd6fa7d6b12fd6352681fb873c5c27" dependencies = [ "chrono", "env_logger", - "fontdrasil", + "fontdrasil 0.2.0", "fontir", "indexmap", "kurbo 0.11.2", "log", "norad 0.15.0", - "ordered-float", + "ordered-float 4.6.0", "plist", "serde", "serde_yaml", "thiserror 1.0.69", - "write-fonts", + "write-fonts 0.38.2", ] [[package]] @@ -2179,7 +2274,7 @@ version = "0.38.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "60491c1d7e5873e721607fa05fd9b9fc66b0f0179b2b5f0f26a2022aafdcc61e" dependencies = [ - "font-types", + "font-types 0.9.0", "indexmap", "kurbo 0.11.2", "log", @@ -2187,6 +2282,20 @@ dependencies = [ "serde", ] +[[package]] +name = "write-fonts" +version = "0.44.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "187aca250ee00f9d9ad3a1ebc9ed65c9c921fdd4690b095ca6e5a8df7246d871" +dependencies = [ + "font-types 0.10.1", + "indexmap", + "kurbo 0.12.0", + "log", + "read-fonts 0.36.0", + "serde", +] + [[package]] name = "writeable" version = "0.6.1" diff --git a/ROADMAP.md b/ROADMAP.md index b6a296c5..c439bc36 100644 --- a/ROADMAP.md +++ b/ROADMAP.md @@ -361,21 +361,21 @@ **Designspace Support** -- [ ] Load `.designspace` files -- [ ] Parse axis definitions (wght, wdth, ital, custom) +- [x] Load `.designspace` files +- [x] Parse axis definitions (wght, wdth, ital, custom) - [ ] Named instances **Masters Editing** -- [ ] Master list panel +- [x] Master list panel - [ ] Switch between masters - [ ] Add/remove masters - [ ] Copy glyph between masters **Interpolation** -- [ ] Compatibility checker (point/contour count) -- [ ] Interpolation preview slider +- [x] Compatibility checker (point/contour count) +- [x] Interpolation preview slider - [ ] Intermediate master insertion - [ ] Extrapolation warning diff --git a/apps/desktop/src/main/managers/AppLifecycle.ts b/apps/desktop/src/main/managers/AppLifecycle.ts index 781c31fa..76fdd021 100644 --- a/apps/desktop/src/main/managers/AppLifecycle.ts +++ b/apps/desktop/src/main/managers/AppLifecycle.ts @@ -207,8 +207,13 @@ export class AppLifecycle { ipc.handle(ipcMain, "dialog:openFont", async () => { const result = await dialog.showOpenDialog({ - properties: ["openFile"], - filters: [{ name: "Fonts", extensions: ["ttf", "otf", "ufo", "glyphs", "glyphspackage"] }], + properties: ["openFile", "openDirectory"], + filters: [ + { + name: "Fonts", + extensions: ["ttf", "otf", "ufo", "glyphs", "glyphspackage", "designspace"], + }, + ], }); if (!result.canceled && result.filePaths[0]) { return result.filePaths[0]; diff --git a/apps/desktop/src/main/managers/MenuManager.ts b/apps/desktop/src/main/managers/MenuManager.ts index f6173258..100493be 100644 --- a/apps/desktop/src/main/managers/MenuManager.ts +++ b/apps/desktop/src/main/managers/MenuManager.ts @@ -118,9 +118,12 @@ export class MenuManager { accelerator: "CmdOrCtrl+O", click: async () => { const result = await dialog.showOpenDialog({ - properties: ["openFile"], + properties: ["openFile", "openDirectory"], filters: [ - { name: "Fonts", extensions: ["ttf", "otf", "ufo", "glyphs", "glyphspackage"] }, + { + name: "Fonts", + extensions: ["ttf", "otf", "ufo", "glyphs", "glyphspackage", "designspace"], + }, ], }); if (!result.canceled && result.filePaths[0]) { diff --git a/apps/desktop/src/main/managers/openFontPath.ts b/apps/desktop/src/main/managers/openFontPath.ts index 515b521b..ca318c03 100644 --- a/apps/desktop/src/main/managers/openFontPath.ts +++ b/apps/desktop/src/main/managers/openFontPath.ts @@ -1,6 +1,13 @@ import path from "node:path"; -const SUPPORTED_FONT_EXTENSIONS = new Set([".ufo", ".ttf", ".otf", ".glyphs", ".glyphspackage"]); +const SUPPORTED_FONT_EXTENSIONS = new Set([ + ".ufo", + ".ttf", + ".otf", + ".glyphs", + ".glyphspackage", + ".designspace", +]); export function isSupportedFontPath(filePath: string): boolean { const ext = path.extname(filePath).toLowerCase(); diff --git a/apps/desktop/src/renderer/src/bridge/NativeBridge.ts b/apps/desktop/src/renderer/src/bridge/NativeBridge.ts index 812c3af3..d8501215 100644 --- a/apps/desktop/src/renderer/src/bridge/NativeBridge.ts +++ b/apps/desktop/src/renderer/src/bridge/NativeBridge.ts @@ -6,6 +6,10 @@ import type { ContourId, Point2D, AnchorId, + Axis, + Source, + GlyphVariationData, + MasterSnapshot, } from "@shift/types"; import { signal, type WritableSignal, type Signal } from "@/lib/reactive/signal"; import type { Bounds } from "@shift/geo"; @@ -22,6 +26,11 @@ import { ContourContent } from "@/lib/clipboard"; import type { NodePositionUpdateList } from "@/types/positionUpdate"; import { Glyph, type GlyphChange } from "@/lib/model/Glyph"; +export interface InterpolationResult { + instance: GlyphSnapshot; + errors: Array<{ sourceIndex: number; sourceName: string; message: string }>; +} + /** * Owns the raw NAPI bridge and the reactive {@link $glyph} signal. * All font queries, session lifecycle, and glyph mutations live here. @@ -135,6 +144,34 @@ export class NativeBridge { return JSON.parse(payload) as CompositeComponentsPayload; } + /** @knipclassignore — used by VariationPanel component */ + isVariable(): boolean { + return this.#raw.isVariable(); + } + + /** @knipclassignore — used by VariationPanel component */ + getAxes(): Axis[] { + return JSON.parse(this.#raw.getAxes()) as Axis[]; + } + + /** @knipclassignore — used by VariationPanel component */ + getSources(): Source[] { + return JSON.parse(this.#raw.getSources()) as Source[]; + } + + /** @knipclassignore — used by VariationPanel component */ + getGlyphMasterSnapshots(glyphName: string): MasterSnapshot[] | null { + const json = this.#raw.getGlyphMasterSnapshots(glyphName); + if (!json) return null; + return JSON.parse(json) as MasterSnapshot[]; + } + + getGlyphVariationData(glyphName: string): GlyphVariationData | null { + const json = this.#raw.getGlyphVariationData(glyphName); + if (!json) return null; + return JSON.parse(json) as GlyphVariationData; + } + getSnapshot(): GlyphSnapshot { return JSON.parse(this.#raw.getSnapshotData()) as GlyphSnapshot; } diff --git a/apps/desktop/src/renderer/src/components/GlyphPreview.tsx b/apps/desktop/src/renderer/src/components/GlyphPreview.tsx index 3d3b74dd..4d1cde69 100644 --- a/apps/desktop/src/renderer/src/components/GlyphPreview.tsx +++ b/apps/desktop/src/renderer/src/components/GlyphPreview.tsx @@ -60,6 +60,9 @@ export const GlyphPreview = memo(function GlyphPreview({ return null; } + // TODO Phase D: wire variation interpolation into glyph grid. + // For now grid always shows the default master; the variation slider only + // affects the canvas glyph via VariationPanel. const svgPath = font.getSvgPath(name); const advance = font.getAdvance(name); const fontMetrics = font.getMetrics(); diff --git a/apps/desktop/src/renderer/src/components/GlyphSidebar.tsx b/apps/desktop/src/renderer/src/components/GlyphSidebar.tsx index 9d097390..5033c4e2 100644 --- a/apps/desktop/src/renderer/src/components/GlyphSidebar.tsx +++ b/apps/desktop/src/renderer/src/components/GlyphSidebar.tsx @@ -9,6 +9,7 @@ import { useSignalEffect } from "@/hooks/useSignalEffect"; import { GlyphSection } from "./sidebar-right/GlyphSection"; import { AnchorSection } from "./sidebar-right/AnchorSection"; import { BooleanOps } from "./BooleanOps"; +import { VariationPanel } from "./VariationPanel"; export const GlyphSidebar = () => { const editor = getEditor(); @@ -42,6 +43,10 @@ export const GlyphSidebar = () => { +
+ +
+ {hasPointSelection && (
diff --git a/apps/desktop/src/renderer/src/components/VariationPanel.tsx b/apps/desktop/src/renderer/src/components/VariationPanel.tsx new file mode 100644 index 00000000..2248fca8 --- /dev/null +++ b/apps/desktop/src/renderer/src/components/VariationPanel.tsx @@ -0,0 +1,180 @@ +import { useCallback, useEffect, useRef, useState } from "react"; +import type { Axis, GlyphVariationData, Source } from "@shift/types"; +import { SidebarSection } from "./sidebar-right/SidebarSection"; +import { getEditor } from "@/store/store"; +import { useSignalState } from "@/lib/reactive"; +import { interpolate, normalize } from "@/lib/interpolation/interpolate"; +import { Input } from "@shift/ui"; + +export const VariationPanel = () => { + const editor = getEditor(); + const font = editor.font; + const fontLoaded = useSignalState(font.$loaded); + + const [axes, setAxes] = useState([]); + const [sources, setSources] = useState([]); + const [location, setLocation] = useState>({}); + const variationDataRef = useRef(null); + const [isInterpolating, setIsInterpolating] = useState(false); + const [editingGlyph, setEditingGlyph] = useState(null); + + useEffect(() => { + if (!fontLoaded || !font.isVariable()) { + setAxes([]); + setSources([]); + return; + } + + const fontAxes = font.getAxes(); + setAxes(fontAxes); + setSources(font.getSources()); + + const defaults: Record = {}; + for (const axis of fontAxes) { + defaults[axis.tag] = axis.default; + } + setLocation(defaults); + }, [fontLoaded, font]); + + useEffect(() => { + setEditingGlyph(editor.getActiveGlyphName()); + }); + + // Fetch variation data ONCE per glyph (cached in ref). Slider scrub reads from + // the cache and never goes back to Rust. TODO Phase D: invalidate on glyph + // commit (needs a commit-version signal on Glyph). + useEffect(() => { + if (axes.length === 0 || !editingGlyph) { + variationDataRef.current = null; + return; + } + variationDataRef.current = font.getGlyphVariationData(editingGlyph); + setIsInterpolating(false); + }, [axes, editingGlyph, font]); + + // Pure JS math, zero NAPI calls. + const applyAt = useCallback( + (newLocation: Record) => { + const data = variationDataRef.current; + if (!data) return; + + const values = interpolate(data, normalize(newLocation, axes)); + const glyph = editor.glyph.peek(); + if (glyph) glyph.applyValues(values); + font.setVariationLocation({ values: newLocation }); + }, + [axes, editor, font], + ); + + const handleAxisChange = useCallback( + (tag: string, value: number) => { + const newLocation = { ...location, [tag]: value }; + setLocation(newLocation); + setIsInterpolating(true); + applyAt(newLocation); + }, + [location, applyAt], + ); + + const handleMasterClick = useCallback( + (source: Source) => { + const newLocation: Record = {}; + for (const axis of axes) { + newLocation[axis.tag] = source.location.values[axis.tag] ?? axis.default; + } + setLocation(newLocation); + setIsInterpolating(true); + applyAt(newLocation); + }, + [axes, applyAt], + ); + + const handleResetToSession = useCallback(() => { + if (!isInterpolating) return; + + setIsInterpolating(false); + font.setVariationLocation(null); + const glyph = editor.glyph.peek(); + if (glyph) { + glyph.restoreSnapshot(glyph.toSnapshot()); + } + + const defaults: Record = {}; + for (const axis of axes) { + defaults[axis.tag] = axis.default; + } + setLocation(defaults); + }, [isInterpolating, editor, font, axes]); + + if (axes.length === 0) return null; + + return ( + +
+ {axes.map((axis) => ( + handleAxisChange(axis.tag, value)} + /> + ))} + {sources.length > 0 && ( +
+ {sources.map((s) => ( + + ))} +
+ )} + {isInterpolating && ( + + )} +
+
+ ); +}; + +interface AxisSliderProps { + axis: Axis; + value: number; + onChange: (value: number) => void; +} + +const AxisSlider = ({ axis, value, onChange }: AxisSliderProps) => { + const displayValue = Math.round(value); + + return ( +
+
+ {axis.name} + {displayValue} +
+ onChange(Number(e.target.value))} + className="w-full h-1.5 bg-[#e0e0e0] rounded-full appearance-none cursor-pointer + [&::-webkit-slider-thumb]:appearance-none [&::-webkit-slider-thumb]:w-3.5 [&::-webkit-slider-thumb]:h-3.5 + [&::-webkit-slider-thumb]:rounded-full [&::-webkit-slider-thumb]:bg-[#333] + [&::-webkit-slider-thumb]:cursor-pointer [&::-webkit-slider-thumb]:border-2 + [&::-webkit-slider-thumb]:border-white [&::-webkit-slider-thumb]:shadow-sm" + /> +
+ ); +}; diff --git a/apps/desktop/src/renderer/src/lib/editor/Editor.ts b/apps/desktop/src/renderer/src/lib/editor/Editor.ts index 21beff61..77fd0bd1 100644 --- a/apps/desktop/src/renderer/src/lib/editor/Editor.ts +++ b/apps/desktop/src/renderer/src/lib/editor/Editor.ts @@ -857,8 +857,7 @@ export class Editor { /** Resolve a unicode codepoint to a glyph ref and insert into the text run. */ public insertTextCodepoint(codepoint: number): void { - const glyphName = this.font.nameForUnicode(codepoint); - if (!glyphName) return; + const glyphName = this.font.glyphName(codepoint); this.#textRunController.insert({ glyphName, unicode: codepoint }); } diff --git a/apps/desktop/src/renderer/src/lib/interpolation/interpolate.test.ts b/apps/desktop/src/renderer/src/lib/interpolation/interpolate.test.ts new file mode 100644 index 00000000..aaf5cde0 --- /dev/null +++ b/apps/desktop/src/renderer/src/lib/interpolation/interpolate.test.ts @@ -0,0 +1,143 @@ +import { describe, it, expect } from "vitest"; +import { readFileSync } from "node:fs"; +import { resolve } from "node:path"; +import type { GlyphVariationData } from "@shift/types"; +import { interpolate, scalarAt, type NormalizedLocation } from "./interpolate"; + +interface MasterEntry { + sourceName: string; + isDefaultSource: boolean; + designspaceLocation: Record; + normalisedLocation: NormalizedLocation; + expected: number[]; +} + +interface Fixture { + glyphName: string; + designspaceTarget: Record; + normalisedLocation: NormalizedLocation; + data: GlyphVariationData; + expected: number[]; + masters: MasterEntry[]; +} + +function loadFixture(): Fixture { + // Generated by `cargo test -p shift-core --test interpolation_parity`. + // vitest runs with cwd at apps/desktop; repo root is two up. + const path = resolve(process.cwd(), "../../packages/types/__fixtures__/variation_parity.json"); + return JSON.parse(readFileSync(path, "utf-8")) as Fixture; +} + +describe("interpolate — parity with fontdrasil", () => { + it("matches Rust interpolate_from_deltas at the fixture target", () => { + const fx = loadFixture(); + const result = interpolate(fx.data, fx.normalisedLocation); + + expect(result.length).toBe(fx.expected.length); + const tolerance = 1e-9; + for (let i = 0; i < result.length; i++) { + const diff = Math.abs(result[i] - fx.expected[i]); + expect( + diff, + `index ${i}: got ${result[i]}, expected ${fx.expected[i]}, diff ${diff}`, + ).toBeLessThan(tolerance); + } + }); + + it("returns the default master values at the origin", () => { + const fx = loadFixture(); + const origin: NormalizedLocation = {}; + for (const tag of Object.keys(fx.normalisedLocation)) origin[tag] = 0; + + const result = interpolate(fx.data, origin); + // Default master = first deltas entry (its region has all-zero tents → scalar 1 + // at origin and elsewhere; other regions have non-zero scalar only off-origin). + // At origin, only the default's contribution should remain. + expect(result.length).toBe(fx.data.deltas[0].length); + for (let i = 0; i < result.length; i++) { + expect(Math.abs(result[i] - fx.data.deltas[0][i])).toBeLessThan(1e-9); + } + }); +}); + +describe("interpolate — round-trip at master locations", () => { + // Strongest defence against unpacking drift: at each master's location, the + // interpolated values must match that master's stored flat geometry. This + // exercises every region's tent in turn (each master sits at exactly one + // off-default region's peak, plus the default region with scalar=1). + it("recovers each master's flat values when interpolating at its own location", () => { + const fx = loadFixture(); + expect(fx.masters.length).toBeGreaterThan(0); + + for (const master of fx.masters) { + const result = interpolate(fx.data, master.normalisedLocation); + + expect(result.length, `${master.sourceName}: length`).toBe(master.expected.length); + for (let i = 0; i < result.length; i++) { + const diff = Math.abs(result[i] - master.expected[i]); + expect( + diff, + `${master.sourceName} index ${i}: got ${result[i]}, expected ${master.expected[i]}, diff ${diff}`, + ).toBeLessThan(1e-9); + } + } + }); + + it("identifies exactly one default master in the fixture", () => { + // Sanity check on the fixture itself — fontdrasil's invariant. + const fx = loadFixture(); + const defaults = fx.masters.filter((m) => m.isDefaultSource); + expect(defaults.length).toBe(1); + }); +}); + +describe("scalarAt — boundary semantics", () => { + it("returns 1 at the peak", () => { + expect(scalarAt({ wght: 0.5 }, [{ axisTag: "wght", lower: 0, peak: 0.5, upper: 1 }])).toBe(1); + }); + + it("returns 0 at the lower boundary (inclusive)", () => { + expect(scalarAt({ wght: 0 }, [{ axisTag: "wght", lower: 0, peak: 0.5, upper: 1 }])).toBe(0); + }); + + it("returns 0 at the upper boundary (inclusive)", () => { + expect(scalarAt({ wght: 1 }, [{ axisTag: "wght", lower: 0, peak: 0.5, upper: 1 }])).toBe(0); + }); + + it("returns 0 outside the tent", () => { + expect(scalarAt({ wght: 1.5 }, [{ axisTag: "wght", lower: 0, peak: 0.5, upper: 1 }])).toBe(0); + expect(scalarAt({ wght: -0.5 }, [{ axisTag: "wght", lower: 0, peak: 0.5, upper: 1 }])).toBe(0); + }); + + it("ramps linearly from lower to peak", () => { + // halfway between lower=0 and peak=0.5 → scalar 0.5 + expect( + scalarAt({ wght: 0.25 }, [{ axisTag: "wght", lower: 0, peak: 0.5, upper: 1 }]), + ).toBeCloseTo(0.5, 9); + }); + + it("ramps linearly from peak to upper", () => { + // halfway between peak=0.5 and upper=1 → scalar 0.5 + expect( + scalarAt({ wght: 0.75 }, [{ axisTag: "wght", lower: 0, peak: 0.5, upper: 1 }]), + ).toBeCloseTo(0.5, 9); + }); + + it("treats (0,0,0) tent as always-on", () => { + // Default-region tents — full influence regardless of location + expect(scalarAt({ wght: 0.7 }, [{ axisTag: "wght", lower: 0, peak: 0, upper: 0 }])).toBe(1); + }); + + it("multiplies scalars across multiple axes", () => { + // Each axis halfway up its ramp → 0.5 × 0.5 = 0.25 + const region = [ + { axisTag: "wght", lower: 0, peak: 0.5, upper: 1 }, + { axisTag: "wdth", lower: 0, peak: 0.5, upper: 1 }, + ]; + expect(scalarAt({ wght: 0.25, wdth: 0.25 }, region)).toBeCloseTo(0.25, 9); + }); + + it("returns 0 for invalid tents (peak < lower)", () => { + expect(scalarAt({ wght: 0.5 }, [{ axisTag: "wght", lower: 0.5, peak: 0, upper: 1 }])).toBe(1); // invalid tent skipped, no other tents → scalar stays 1 + }); +}); diff --git a/apps/desktop/src/renderer/src/lib/interpolation/interpolate.ts b/apps/desktop/src/renderer/src/lib/interpolation/interpolate.ts new file mode 100644 index 00000000..fac5dd33 --- /dev/null +++ b/apps/desktop/src/renderer/src/lib/interpolation/interpolate.ts @@ -0,0 +1,91 @@ +/** + * Variable-font interpolation — per-tick eval path. + * + * The hard math (region construction + delta decomposition) lives in Rust via + * `fontdrasil`. This module is the trivial per-tick eval — region tent function + * and a dot product against cached deltas. Ported faithfully from fontdrasil's + * `scalar_at_with_args` and `interpolate_from_deltas`. + * + * Parity-tested against `packages/types/__fixtures__/variation_parity.json`, + * generated by `crates/shift-core/tests/interpolation_parity.rs`. + */ + +import type { Axis, AxisTent, GlyphVariationData } from "@shift/types"; + +export type NormalizedLocation = Record; +export type DesignspaceLocation = Record; + +/** Asymmetric normalize — mirrors `Axis::normalize` in shift-ir/src/axis.rs. */ +export function normalizeAxis(value: number, axis: Axis): number { + if (value < axis.default) { + const range = axis.default - axis.minimum; + return range === 0 ? 0 : (value - axis.default) / range; + } + if (value > axis.default) { + const range = axis.maximum - axis.default; + return range === 0 ? 0 : (value - axis.default) / range; + } + return 0; +} + +export function normalize(loc: DesignspaceLocation, axes: Axis[]): NormalizedLocation { + const out: NormalizedLocation = {}; + for (const axis of axes) { + out[axis.tag] = normalizeAxis(loc[axis.tag] ?? axis.default, axis); + } + return out; +} + +/** Mirrors fontdrasil's `Tent::validate` — used as a per-tent filter. */ +function isValidTent(t: AxisTent): boolean { + if (t.lower > t.peak || t.peak > t.upper) return false; + if (t.lower < 0 && t.upper > 0) return false; // can't span across default + return true; +} + +/** + * Scalar contribution of a region at a normalized location. + * Exact port of fontdrasil's `VariationRegion::scalar_at_with_args` (no extrapolation). + */ +export function scalarAt(loc: NormalizedLocation, region: AxisTent[]): number { + let scalar = 1; + for (const t of region) { + if (!isValidTent(t)) continue; + + const v = loc[t.axisTag] ?? 0; + + if (v === t.peak) continue; + + if (t.lower === 0 && t.peak === 0 && t.upper === 0) { + continue; // (0,0,0) tent = always-on (default region) + } + + if (v <= t.lower || t.upper <= v) return 0; // outside, boundary inclusive + + const edge = v < t.peak ? t.lower : t.upper; + scalar *= (v - edge) / (t.peak - edge); + } + return scalar; +} + +/** + * Evaluate per-region deltas at a normalized location. + * Exact port of fontdrasil's `VariationModel::interpolate_from_deltas` (no extrapolation). + * + * Output values are absolute (not offsets from default) because the default + * master's region has empty/zero support and contributes its full delta at scalar=1. + * + * Order is the `flatten()` shape from shift-core::interpolation: + * [xAdvance, p0.x, p0.y, p1.x, p1.y, ..., a0.x, a0.y, ...] + */ +export function interpolate(data: GlyphVariationData, loc: NormalizedLocation): Float64Array { + const len = data.deltas[0]?.length ?? 0; + const result = new Float64Array(len); + for (let r = 0; r < data.regions.length; r++) { + const s = scalarAt(loc, data.regions[r]); + if (s === 0) continue; + const d = data.deltas[r]; + for (let i = 0; i < len; i++) result[i] += s * d[i]; + } + return result; +} diff --git a/apps/desktop/src/renderer/src/lib/model/Font.ts b/apps/desktop/src/renderer/src/lib/model/Font.ts index 48287038..3a05da47 100644 --- a/apps/desktop/src/renderer/src/lib/model/Font.ts +++ b/apps/desktop/src/renderer/src/lib/model/Font.ts @@ -1,4 +1,13 @@ -import type { FontMetrics, FontMetadata, CompositeGlyph } from "@shift/types"; +import type { + FontMetrics, + FontMetadata, + CompositeGlyph, + Axis, + Source, + Location, + GlyphVariationData, +} from "@shift/types"; +import type { MasterSnapshot } from "@shift/types"; import type { Bounds } from "@shift/geo"; import { signal, type WritableSignal, type Signal } from "@/lib/reactive/signal"; import type { NativeBridge } from "@/bridge"; @@ -15,12 +24,14 @@ export class Font { readonly #$loaded: WritableSignal; readonly #$unicodes: WritableSignal; readonly #$metrics: WritableSignal; + readonly #$variationLocation: WritableSignal; constructor(bridge: NativeBridge) { this.#bridge = bridge; this.#$loaded = signal(false); this.#$unicodes = signal([]); this.#$metrics = signal(null); + this.#$variationLocation = signal(null); } /** @knipclassignore */ @@ -93,6 +104,41 @@ export class Font { return this.#bridge.getSvgPath(name); } + /** @knipclassignore — used by GlyphPreview for variation interpolation */ + get $variationLocation(): Signal { + return this.#$variationLocation; + } + + /** @knipclassignore — used by VariationPanel */ + setVariationLocation(location: Location | null): void { + this.#$variationLocation.set(location); + } + + /** @knipclassignore — used by VariationPanel component */ + isVariable(): boolean { + return this.#bridge.isVariable(); + } + + /** @knipclassignore — used by VariationPanel component */ + getAxes(): Axis[] { + return this.#bridge.getAxes(); + } + + /** @knipclassignore — used by VariationPanel component */ + getSources(): Source[] { + return this.#bridge.getSources(); + } + + /** @knipclassignore — used by VariationPanel component */ + getGlyphMasterSnapshots(glyphName: string): MasterSnapshot[] | null { + return this.#bridge.getGlyphMasterSnapshots(glyphName); + } + + /** @knipclassignore — used by VariationPanel component */ + getGlyphVariationData(glyphName: string): GlyphVariationData | null { + return this.#bridge.getGlyphVariationData(glyphName); + } + composites(glyphName: string): CompositeGlyph | null { return this.#bridge.getGlyphCompositeComponents(glyphName) as CompositeGlyph | null; } diff --git a/apps/desktop/src/renderer/src/lib/model/Glyph.ts b/apps/desktop/src/renderer/src/lib/model/Glyph.ts index 30a3ae4e..5330fe1f 100644 --- a/apps/desktop/src/renderer/src/lib/model/Glyph.ts +++ b/apps/desktop/src/renderer/src/lib/model/Glyph.ts @@ -522,6 +522,62 @@ export class Glyph { } } + /** + * @knipclassignore — used by VariationPanel for live interpolation + * + * Apply interpolated values from variation math. + * + * `values` order MUST match `flatten()` in crates/shift-core/src/interpolation.rs: + * [xAdvance, p0.x, p0.y, p1.x, p1.y, ..., a0.x, a0.y, ...] + * + * In-place patch — reuses Point/Contour/Anchor identities, fires per-contour + * signals via a single batch. No struct allocation tree, no JSON parse, no + * NAPI hop on the hot path. + * + * Length-checked at runtime to catch drift between Rust's flatten() walk and + * this one. Round-trip-tested in interpolate.test.ts (parity test ensures + * the values themselves are correct). + */ + applyValues(values: Float64Array): void { + const contours = this.#contours.peek(); + const anchors = this.#anchors.peek(); + + let expected = 1; // xAdvance + for (const c of contours) expected += c.points.length * 2; + expected += anchors.length * 2; + + if (values.length !== expected) { + throw new Error( + `Glyph.applyValues: length mismatch — got ${values.length}, expected ${expected}. ` + + `flatten() in shift-core::interpolation may have drifted from this walk.`, + ); + } + + batch(() => { + let i = 0; + this.#xAdvance.set(values[i++]); + + for (const contour of contours) { + contour._setPoints( + contour.points.map((pt) => { + const x = values[i++]; + const y = values[i++]; + return { ...pt, x, y }; + }), + ); + } + this.#contours.set([...contours]); + + this.#anchors.set( + anchors.map((a) => { + const x = values[i++]; + const y = values[i++]; + return { ...a, x, y }; + }), + ); + }); + } + /** Extract current reactive state as a plain snapshot (for undo, Rust sync). */ toSnapshot(): GlyphSnapshot { return { diff --git a/crates/shift-backends/src/designspace/mod.rs b/crates/shift-backends/src/designspace/mod.rs new file mode 100644 index 00000000..df76ba27 --- /dev/null +++ b/crates/shift-backends/src/designspace/mod.rs @@ -0,0 +1,3 @@ +mod reader; + +pub use reader::DesignspaceReader; diff --git a/crates/shift-backends/src/designspace/reader.rs b/crates/shift-backends/src/designspace/reader.rs new file mode 100644 index 00000000..49e98897 --- /dev/null +++ b/crates/shift-backends/src/designspace/reader.rs @@ -0,0 +1,321 @@ +use crate::traits::FontReader; +use crate::ufo::UfoReader; +use norad::designspace::DesignSpaceDocument; +use shift_ir::{Axis, Font, Layer, LayerId, Location, Source}; +use std::collections::HashMap; +use std::path::Path; + +pub struct DesignspaceReader; + +impl DesignspaceReader { + pub fn new() -> Self { + Self + } +} + +impl Default for DesignspaceReader { + fn default() -> Self { + Self::new() + } +} + +impl FontReader for DesignspaceReader { + fn load(&self, path: &str) -> Result { + let ds_path = Path::new(path); + let ds_dir = ds_path + .parent() + .ok_or_else(|| format!("Cannot determine directory of '{path}'"))?; + + let doc = DesignSpaceDocument::load(ds_path) + .map_err(|e| format!("Failed to load designspace '{path}': {e}"))?; + + if doc.sources.is_empty() { + return Err("Designspace has no sources".to_string()); + } + + let default_idx = find_default_source_index(&doc); + + // Load the default source first to establish the base font. + let default_ds_source = &doc.sources[default_idx]; + let default_ufo_path = ds_dir.join(&default_ds_source.filename); + let default_ufo_str = default_ufo_path + .to_str() + .ok_or_else(|| "Invalid UTF-8 in default UFO path".to_string())?; + + let ufo_reader = UfoReader::new(); + let mut font = ufo_reader.load(default_ufo_str)?; + + if let Some(ref family) = default_ds_source.familyname { + font.metadata_mut().family_name = Some(family.clone()); + } + + // Add axes. + for ds_axis in &doc.axes { + let (minimum, maximum) = derive_axis_range(ds_axis); + let mut axis = Axis::new( + ds_axis.tag.clone(), + ds_axis.name.clone(), + minimum, + ds_axis.default as f64, + maximum, + ); + axis.set_hidden(ds_axis.hidden); + font.add_axis(axis); + } + + // Register the default source. + let default_layer_id = font.default_layer_id(); + let default_location = location_from_dimensions(&default_ds_source.location, &doc); + let default_name = source_name(default_ds_source, default_idx); + let default_source_id = font.add_source(Source::with_filename( + default_name, + default_location, + default_layer_id, + default_ds_source.filename.clone(), + )); + font.set_default_source_id(default_source_id); + + // Cache loaded UFO fonts so we don't re-read the same file for support layers. + let mut ufo_cache: HashMap = HashMap::new(); + + // Load each non-default source. + for (idx, ds_source) in doc.sources.iter().enumerate() { + if idx == default_idx { + continue; + } + + let ufo_path = ds_dir.join(&ds_source.filename); + let ufo_str = ufo_path + .to_str() + .ok_or_else(|| format!("Invalid UTF-8 in UFO path: {ufo_path:?}"))? + .to_string(); + + let source_font = match ufo_cache.get(&ufo_str) { + Some(f) => f, + None => { + let loaded = ufo_reader.load(&ufo_str)?; + ufo_cache.insert(ufo_str.clone(), loaded); + ufo_cache.get(&ufo_str).unwrap() + } + }; + + // Determine which layer from the source UFO to read. + let source_layer_id = match &ds_source.layer { + Some(layer_name) => { + find_layer_by_name(source_font, layer_name).ok_or_else(|| { + format!( + "Layer '{}' not found in '{}'", + layer_name, ds_source.filename + ) + })? + } + None => source_font.default_layer_id(), + }; + + let name = source_name(ds_source, idx); + let layer = Layer::new(name.clone()); + let layer_id = font.add_layer(layer); + + // Copy glyphs from the resolved layer into the new layer. + for (glyph_name, source_glyph) in source_font.glyphs() { + if let Some(source_layer) = source_glyph.layer(source_layer_id) { + if let Some(existing_glyph) = font.glyph_mut(glyph_name) { + existing_glyph.set_layer(layer_id, source_layer.clone()); + } + } + } + + let location = location_from_dimensions(&ds_source.location, &doc); + font.add_source(Source::with_filename( + name, + location, + layer_id, + ds_source.filename.clone(), + )); + } + + Ok(font) + } +} + +fn source_name(source: &norad::designspace::Source, index: usize) -> String { + source + .name + .clone() + .or_else(|| source.stylename.clone()) + .unwrap_or_else(|| format!("Source {index}")) +} + +fn location_from_dimensions( + dimensions: &[norad::designspace::Dimension], + doc: &DesignSpaceDocument, +) -> Location { + let mut location = Location::new(); + for dim in dimensions { + let value = dim.xvalue.unwrap_or(0.0) as f64; + if let Some(axis) = doc.axes.iter().find(|a| a.name == dim.name) { + location.set(axis.tag.clone(), value); + } + } + location +} + +fn find_default_source_index(doc: &DesignSpaceDocument) -> usize { + for (idx, source) in doc.sources.iter().enumerate() { + // Skip support layer sources. + if source.layer.is_some() { + continue; + } + + let is_default = doc.axes.iter().all(|axis| { + source + .location + .iter() + .find(|d| d.name == axis.name) + .map(|d| { + let val = d.xvalue.unwrap_or(0.0); + (val - axis.default).abs() < 0.001 + }) + .unwrap_or(false) + }); + if is_default { + return idx; + } + } + 0 +} + +fn find_layer_by_name(font: &Font, name: &str) -> Option { + font.layers() + .iter() + .find(|(_, layer)| layer.name() == name) + .map(|(&id, _)| id) +} + +/// Derive (minimum, maximum) for an axis from norad's parsed designspace. +/// +/// Designspace axis edge cases handled: +/// - **Continuous** (both min/max present): use as-is. +/// - **Discrete** (`values="0 1"` with no min/max attrs): min/max are the +/// smallest/largest values in the list. e.g. `ital`, our `SLAB`. +/// - **One-sided** (only min OR max specified): the missing side falls back +/// to `default`. Common with slant axes (`min=-15, default=0, max=0`). +/// - **Degenerate** (no min/max/values): all three collapse to default. +fn derive_axis_range(ds_axis: &norad::designspace::Axis) -> (f64, f64) { + let values_range = || { + ds_axis + .values + .as_ref() + .filter(|v| !v.is_empty()) + .map(|values| { + let min = values.iter().cloned().fold(f32::INFINITY, f32::min) as f64; + let max = values.iter().cloned().fold(f32::NEG_INFINITY, f32::max) as f64; + (min, max) + }) + }; + + match (ds_axis.minimum, ds_axis.maximum) { + (Some(min), Some(max)) => (min as f64, max as f64), + (None, None) => values_range().unwrap_or((ds_axis.default as f64, ds_axis.default as f64)), + (Some(min), None) => (min as f64, ds_axis.default as f64), + (None, Some(max)) => (ds_axis.default as f64, max as f64), + } +} + +#[cfg(test)] +mod axis_range_tests { + use super::*; + use norad::designspace::Axis as DsAxis; + + fn axis(min: Option, max: Option, default: f32, values: Option>) -> DsAxis { + DsAxis { + name: "test".into(), + tag: "TEST".into(), + minimum: min, + maximum: max, + default, + hidden: false, + values, + ..Default::default() + } + } + + #[test] + fn continuous_uses_explicit_min_max() { + let a = axis(Some(100.0), Some(900.0), 400.0, None); + assert_eq!(derive_axis_range(&a), (100.0, 900.0)); + } + + #[test] + fn discrete_two_values_derives_range() { + // SLAB axis pattern: + let a = axis(None, None, 0.0, Some(vec![0.0, 1.0])); + assert_eq!(derive_axis_range(&a), (0.0, 1.0)); + } + + #[test] + fn discrete_three_values_derives_range_from_extremes() { + let a = axis(None, None, 1.0, Some(vec![0.5, 1.0, 1.5])); + assert_eq!(derive_axis_range(&a), (0.5, 1.5)); + } + + #[test] + fn discrete_unsorted_values_still_finds_extremes() { + let a = axis(None, None, 1.0, Some(vec![1.5, 0.5, 1.0])); + assert_eq!(derive_axis_range(&a), (0.5, 1.5)); + } + + #[test] + fn explicit_min_max_takes_precedence_over_values() { + let a = axis(Some(0.0), Some(2.0), 1.0, Some(vec![0.5, 1.5])); + assert_eq!(derive_axis_range(&a), (0.0, 2.0)); + } + + #[test] + fn one_sided_min_only_falls_back_to_default_for_max() { + // slant-like, half-spec'd: min=-15, default=0, no max attr + let a = axis(Some(-15.0), None, 0.0, None); + assert_eq!(derive_axis_range(&a), (-15.0, 0.0)); + } + + #[test] + fn one_sided_max_only_falls_back_to_default_for_min() { + let a = axis(None, Some(900.0), 400.0, None); + assert_eq!(derive_axis_range(&a), (400.0, 900.0)); + } + + #[test] + fn no_min_max_no_values_collapses_to_default() { + let a = axis(None, None, 400.0, None); + assert_eq!(derive_axis_range(&a), (400.0, 400.0)); + } + + #[test] + fn empty_values_list_collapses_to_default() { + let a = axis(None, None, 0.0, Some(vec![])); + assert_eq!(derive_axis_range(&a), (0.0, 0.0)); + } + + #[test] + fn asymmetric_default_at_minimum() { + // Older fonts where the Light is the default + let a = axis(Some(400.0), Some(900.0), 400.0, None); + assert_eq!(derive_axis_range(&a), (400.0, 900.0)); + // The Axis itself should still normalise sensibly: + let axis = Axis::new("wght".into(), "Weight".into(), 400.0, 400.0, 900.0); + assert_eq!(axis.normalize(400.0), 0.0); + assert_eq!(axis.normalize(900.0), 1.0); + // Below default: range is zero, must return 0 (no negative ramp). + assert_eq!(axis.normalize(100.0), 0.0); + } + + #[test] + fn asymmetric_one_sided_negative_axis() { + // slnt-like: min=-15, default=0, max=0 + let axis = Axis::new("slnt".into(), "Slant".into(), -15.0, 0.0, 0.0); + assert_eq!(axis.normalize(0.0), 0.0); + assert_eq!(axis.normalize(-15.0), -1.0); + // Above default: range is zero, returns 0 (no positive ramp). + assert_eq!(axis.normalize(5.0), 0.0); + } +} diff --git a/crates/shift-backends/src/glyphs/reader.rs b/crates/shift-backends/src/glyphs/reader.rs index 351f7218..b9f0032b 100644 --- a/crates/shift-backends/src/glyphs/reader.rs +++ b/crates/shift-backends/src/glyphs/reader.rs @@ -196,7 +196,10 @@ impl FontReader for GlyphsReader { location.set(axis.tag.clone(), value.into_inner()); } } - font.add_source(Source::new(master.name.clone(), location, layer_id)); + let source_id = font.add_source(Source::new(master.name.clone(), location, layer_id)); + if master_idx == glyphs_font.default_master_idx { + font.set_default_source_id(source_id); + } } for glyph in glyphs_font.glyphs.values() { diff --git a/crates/shift-backends/src/lib.rs b/crates/shift-backends/src/lib.rs index f0019a39..92c9d740 100644 --- a/crates/shift-backends/src/lib.rs +++ b/crates/shift-backends/src/lib.rs @@ -1,3 +1,4 @@ +pub mod designspace; pub mod glyphs; mod traits; pub mod ufo; diff --git a/crates/shift-backends/src/ufo/reader.rs b/crates/shift-backends/src/ufo/reader.rs index 3d8c6431..6937074a 100644 --- a/crates/shift-backends/src/ufo/reader.rs +++ b/crates/shift-backends/src/ufo/reader.rs @@ -239,8 +239,9 @@ impl FontReader for UfoReader { font.metrics_mut().x_height = norad_font.font_info.x_height; font.metrics_mut().italic_angle = norad_font.font_info.italic_angle; + let norad_default_layer_name = norad_font.layers.default_layer().name().clone(); for layer in norad_font.layers.iter() { - let layer_id = if layer.name().as_str() == "public.default" { + let layer_id = if layer.name() == &norad_default_layer_name { default_layer_id } else { let new_layer = Layer::new(layer.name().to_string()); diff --git a/crates/shift-core/Cargo.toml b/crates/shift-core/Cargo.toml index 0dcc6033..28cb1cab 100644 --- a/crates/shift-core/Cargo.toml +++ b/crates/shift-core/Cargo.toml @@ -9,6 +9,7 @@ crate-type = ["rlib"] [dependencies] bitflags = "2.9.1" fontc = "0.2.0" +fontdrasil = "0.4.0" norad = "0.16.0" serde = { version = "1.0.219", features = ["derive"] } serde_json = "1.0" diff --git a/crates/shift-core/src/font_loader.rs b/crates/shift-core/src/font_loader.rs index d0e88a88..f618efc3 100644 --- a/crates/shift-core/src/font_loader.rs +++ b/crates/shift-core/src/font_loader.rs @@ -2,6 +2,7 @@ use std::collections::HashMap; use std::path::Path; use crate::binary::BytesFontAdaptor; +use shift_backends::designspace::DesignspaceReader; use shift_backends::glyphs::GlyphsReader; use shift_backends::ufo::UfoReader; use shift_backends::FontReader; @@ -11,6 +12,7 @@ use shift_ir::Font; pub enum FontFormat { Ufo, Glyphs, + Designspace, Ttf, Otf, } @@ -22,6 +24,7 @@ pub trait FontAdaptor { struct UfoFontAdaptor; struct GlyphsFontAdaptor; +struct DesignspaceFontAdaptor; impl FontAdaptor for UfoFontAdaptor { fn read_font(&self, path: &str) -> Result { @@ -45,6 +48,16 @@ impl FontAdaptor for GlyphsFontAdaptor { } } +impl FontAdaptor for DesignspaceFontAdaptor { + fn read_font(&self, path: &str) -> Result { + DesignspaceReader::new().load(path) + } + + fn write_font(&self, _font: &Font, _path: &str) -> Result<(), String> { + Err("Designspace writing is not supported; save as .ufo instead".to_string()) + } +} + pub struct FontLoader { adaptors: HashMap>, } @@ -60,6 +73,7 @@ fn format_from_extension(ext: &str) -> Result { "ufo" => Ok(FontFormat::Ufo), "glyphs" => Ok(FontFormat::Glyphs), "glyphspackage" => Ok(FontFormat::Glyphs), + "designspace" => Ok(FontFormat::Designspace), "ttf" => Ok(FontFormat::Ttf), "otf" => Ok(FontFormat::Otf), _ => Err(format!("Unsupported font format: {ext}")), @@ -78,6 +92,7 @@ impl FontLoader { let mut adaptors: HashMap> = HashMap::new(); adaptors.insert(FontFormat::Ufo, Box::new(UfoFontAdaptor)); adaptors.insert(FontFormat::Glyphs, Box::new(GlyphsFontAdaptor)); + adaptors.insert(FontFormat::Designspace, Box::new(DesignspaceFontAdaptor)); adaptors.insert(FontFormat::Ttf, Box::new(BytesFontAdaptor)); adaptors.insert(FontFormat::Otf, Box::new(BytesFontAdaptor)); @@ -130,6 +145,14 @@ mod tests { )); } + #[test] + fn supports_designspace_extension() { + assert!(matches!( + format_from_extension("designspace"), + Ok(FontFormat::Designspace) + )); + } + #[test] fn extension_matching_is_case_insensitive() { assert!(matches!(format_from_extension("UFO"), Ok(FontFormat::Ufo))); @@ -138,5 +161,9 @@ mod tests { Ok(FontFormat::Glyphs) )); assert!(matches!(format_from_extension("OTF"), Ok(FontFormat::Otf))); + assert!(matches!( + format_from_extension("DESIGNSPACE"), + Ok(FontFormat::Designspace) + )); } } diff --git a/crates/shift-core/src/interpolation.rs b/crates/shift-core/src/interpolation.rs new file mode 100644 index 00000000..6f47c21f --- /dev/null +++ b/crates/shift-core/src/interpolation.rs @@ -0,0 +1,191 @@ +use std::collections::{HashMap, HashSet}; +use std::str::FromStr; + +use fontdrasil::coords::NormalizedLocation; +use fontdrasil::types::Tag; +use fontdrasil::variations::VariationModel; +use serde::{Deserialize, Serialize}; +use shift_ir::variation::to_fd_location; +use shift_ir::Axis; +use ts_rs::TS; + +use crate::snapshot::{AnchorSnapshot, ContourSnapshot, GlyphGeometry, MasterSnapshot}; +use crate::{Font, Glyph}; + +#[derive(Debug, Clone, Serialize, Deserialize, TS)] +#[serde(rename_all = "camelCase")] +#[ts(export, export_to = "../../../packages/types/src/generated/")] +pub struct AxisTent { + pub axis_tag: String, + pub lower: f64, + pub peak: f64, + pub upper: f64, +} + +#[derive(Debug, Clone, Serialize, Deserialize, TS)] +#[serde(rename_all = "camelCase")] +#[ts(export, export_to = "../../../packages/types/src/generated/")] +pub struct GlyphVariationData { + /// One entry per region. Inner = tents on the axes the region depends on. + pub regions: Vec>, + /// Same length as `regions`. Each entry = flat values matching `flatten()` order: + /// [xAdvance, p0.x, p0.y, ..., a0.x, a0.y, ...]. + pub deltas: Vec>, +} + +#[derive(Debug, Clone, Serialize, Deserialize, TS)] +#[serde(rename_all = "camelCase")] +#[ts(export, export_to = "../../../packages/types/src/generated/")] +pub struct SourceError { + #[ts(type = "number")] + pub source_index: usize, + pub source_name: String, + pub message: String, +} + +fn flatten(geom: &GlyphGeometry) -> Vec { + let mut values = vec![geom.x_advance]; + for contour in &geom.contours { + for point in &contour.points { + values.push(point.x); + values.push(point.y); + } + } + for anchor in &geom.anchors { + values.push(anchor.x); + values.push(anchor.y); + } + values +} + +fn check_compatibility(a: &GlyphGeometry, b: &GlyphGeometry) -> Result<(), String> { + if a.contours.len() != b.contours.len() { + return Err(format!( + "contour count mismatch: {} vs {}", + a.contours.len(), + b.contours.len() + )); + } + for (i, (ca, cb)) in a.contours.iter().zip(b.contours.iter()).enumerate() { + if ca.points.len() != cb.points.len() { + return Err(format!( + "contour {} point count mismatch: {} vs {}", + i, + ca.points.len(), + cb.points.len() + )); + } + } + if a.anchors.len() != b.anchors.len() { + return Err(format!( + "anchor count mismatch: {} vs {}", + a.anchors.len(), + b.anchors.len() + )); + } + Ok(()) +} + +/// Build per-master snapshots of a single glyph. +/// +/// Pure: no editing-session knowledge. Caller passes the `Glyph` it wants the +/// snapshots from (could be the disk copy or an in-progress editing copy with +/// the live session layer patched in — `shift-node` handles that detour). +/// +/// Returns `None` if the font isn't variable or no source has a non-empty layer +/// for this glyph. +pub fn build_master_snapshots(font: &Font, glyph: &Glyph) -> Option> { + if !font.is_variable() { + return None; + } + + let default_source_id = font.default_source_id(); + let mut masters: Vec = Vec::new(); + + for source in font.sources() { + let layer = match glyph.layer(source.layer_id()) { + Some(l) if !l.contours().is_empty() => l, + _ => continue, + }; + + let contours: Vec = layer + .contours() + .values() + .filter(|c| !c.points().is_empty()) + .map(ContourSnapshot::from) + .collect(); + + let anchors: Vec = layer.anchors_iter().map(AnchorSnapshot::from).collect(); + + masters.push(MasterSnapshot { + source_id: source.id().raw().to_string(), + source_name: source.name().to_string(), + is_default_source: default_source_id == Some(source.id()), + location: source.location().clone(), + geometry: GlyphGeometry { + x_advance: layer.width(), + contours, + anchors, + }, + }); + } + + if masters.is_empty() { + None + } else { + Some(masters) + } +} + +pub fn get_glyph_variation_data( + masters: &[MasterSnapshot], + axes: &[Axis], +) -> Option { + let ordered_axes: Vec = axes + .iter() + .filter_map(|a| Tag::from_str(a.tag()).ok()) + .collect(); + + let default_master = masters.iter().find(|master| master.is_default_source)?; + + let mut errors = Vec::new(); + let mut points: HashMap> = HashMap::new(); + for (source_index, master) in masters.iter().enumerate() { + match check_compatibility(&master.geometry, &default_master.geometry) { + Ok(()) => { + let loc = to_fd_location(&master.location, axes); + points.insert(loc, flatten(&master.geometry)); + } + Err(message) => { + errors.push(SourceError { + source_index, + source_name: master.source_name.clone(), + message, + }); + } + } + } + + let locations_set: HashSet = points.keys().cloned().collect(); + let model = VariationModel::new(locations_set, ordered_axes); + let model_deltas = model.deltas::(&points).ok()?; + + let regions: Vec> = model_deltas + .iter() + .map(|(region, _)| { + region + .iter() + .map(|(tag, tent)| AxisTent { + axis_tag: tag.to_string(), + lower: tent.min.into_inner().into_inner(), + peak: tent.peak.into_inner().into_inner(), + upper: tent.max.into_inner().into_inner(), + }) + .collect() + }) + .collect(); + + let deltas: Vec> = model_deltas.into_iter().map(|(_, d)| d).collect(); + + Some(GlyphVariationData { regions, deltas }) +} diff --git a/crates/shift-core/src/lib.rs b/crates/shift-core/src/lib.rs index f4d1aa0b..ae75a7dd 100644 --- a/crates/shift-core/src/lib.rs +++ b/crates/shift-core/src/lib.rs @@ -5,13 +5,14 @@ pub mod curve; pub mod dependency_graph; pub mod edit_session; pub mod font_loader; +pub mod interpolation; pub mod snapshot; pub mod vec2; pub use shift_ir::{ - Anchor, AnchorId, BooleanOp, Contour, ContourId, CurveSegment, CurveSegmentIter, Font, - FontMetadata, FontMetrics, Glyph, GlyphLayer, GlyphName, GuidelineId, LayerId, Point, PointId, - PointType, Transform, + Anchor, AnchorId, Axis, BooleanOp, Contour, ContourId, CurveSegment, CurveSegmentIter, Font, + FontMetadata, FontMetrics, Glyph, GlyphLayer, GlyphName, GuidelineId, LayerId, Location, Point, + PointId, PointType, Source, SourceId, Transform, }; pub use shift_backends::ufo::{UfoReader, UfoWriter}; diff --git a/crates/shift-core/src/snapshot.rs b/crates/shift-core/src/snapshot.rs index 4e80a63f..30df70f5 100644 --- a/crates/shift-core/src/snapshot.rs +++ b/crates/shift-core/src/snapshot.rs @@ -1,7 +1,9 @@ use serde::{Deserialize, Serialize}; use ts_rs::TS; -use crate::{edit_session::EditSession, Anchor, Contour, Point, PointId, PointType as IrPointType}; +use crate::{ + edit_session::EditSession, Anchor, Contour, Location, Point, PointId, PointType as IrPointType, +}; #[derive(Debug, Clone, Serialize, Deserialize, TS)] #[serde(rename_all = "camelCase")] @@ -129,6 +131,26 @@ impl From<&Contour> for RenderContourSnapshot { } } +#[derive(Debug, Clone, Serialize, Deserialize, TS)] +#[serde(rename_all = "camelCase")] +#[ts(export, export_to = "../../../packages/types/src/generated/")] +pub struct GlyphGeometry { + #[ts(rename = "xAdvance")] + pub x_advance: f64, + pub contours: Vec, + pub anchors: Vec, +} + +impl From<&GlyphSnapshot> for GlyphGeometry { + fn from(snap: &GlyphSnapshot) -> Self { + Self { + x_advance: snap.x_advance, + contours: snap.contours.clone(), + anchors: snap.anchors.clone(), + } + } +} + #[derive(Debug, Clone, Serialize, Deserialize, TS)] #[serde(rename_all = "camelCase")] #[ts(export, export_to = "../../../packages/types/src/generated/")] @@ -220,6 +242,17 @@ impl CommandResult { } } +#[derive(Debug, Clone, Serialize, Deserialize, TS)] +#[serde(rename_all = "camelCase")] +#[ts(export, export_to = "../../../packages/types/src/generated/")] +pub struct MasterSnapshot { + pub source_id: String, + pub source_name: String, + pub is_default_source: bool, + pub location: Location, + pub geometry: GlyphGeometry, +} + #[cfg(test)] mod tests { use super::*; diff --git a/crates/shift-core/tests/font_loading.rs b/crates/shift-core/tests/font_loading.rs index 6c773cc2..5864f4ab 100644 --- a/crates/shift-core/tests/font_loading.rs +++ b/crates/shift-core/tests/font_loading.rs @@ -483,3 +483,186 @@ fn test_otf_has_glyph_contours() { "OTF glyph 'A' should have contours" ); } + +// --- Variable font (multi-master .glyphs) tests --- + +fn mutatorsans_variable_glyphs_path() -> PathBuf { + fixtures_path().join("fonts/MutatorSansVariable.glyphs") +} + +#[test] +fn test_variable_glyphs_is_variable() { + let path = mutatorsans_variable_glyphs_path(); + let loader = FontLoader::new(); + let font = loader + .read_font(path.to_str().unwrap()) + .expect("Failed to load variable .glyphs font"); + + assert!(font.is_variable(), "Multi-master font should be variable"); +} + +#[test] +fn test_variable_glyphs_axes() { + let path = mutatorsans_variable_glyphs_path(); + let loader = FontLoader::new(); + let font = loader.read_font(path.to_str().unwrap()).unwrap(); + + let axes = font.axes(); + assert_eq!(axes.len(), 1, "Should have 1 axis"); + assert_eq!(axes[0].tag(), "wght"); + assert_eq!(axes[0].name(), "Weight"); + assert_eq!(axes[0].minimum(), 100.0); + assert_eq!(axes[0].maximum(), 900.0); + assert_eq!(axes[0].default(), 100.0); +} + +#[test] +fn test_variable_glyphs_sources() { + let path = mutatorsans_variable_glyphs_path(); + let loader = FontLoader::new(); + let font = loader.read_font(path.to_str().unwrap()).unwrap(); + + let sources = font.sources(); + assert_eq!(sources.len(), 2, "Should have 2 sources (Light and Bold)"); + + let light = &sources[0]; + assert_eq!(light.location().get("wght"), Some(100.0)); + + let bold = &sources[1]; + assert_eq!(bold.location().get("wght"), Some(900.0)); +} + +#[test] +fn test_variable_glyphs_glyph_has_multiple_layers() { + let path = mutatorsans_variable_glyphs_path(); + let loader = FontLoader::new(); + let font = loader.read_font(path.to_str().unwrap()).unwrap(); + + let glyph_a = font.glyph("A").expect("Glyph 'A' should exist"); + assert_eq!( + glyph_a.layers().len(), + 2, + "Variable glyph 'A' should have 2 layers (one per master)" + ); +} + +#[test] +fn test_variable_glyphs_masters_are_compatible() { + let path = mutatorsans_variable_glyphs_path(); + let loader = FontLoader::new(); + let font = loader.read_font(path.to_str().unwrap()).unwrap(); + + let glyph_a = font.glyph("A").expect("Glyph 'A' should exist"); + let layers: Vec<_> = glyph_a.layers().values().collect(); + assert_eq!(layers.len(), 2); + + // Both layers should have the same number of contours + assert_eq!( + layers[0].contours().len(), + layers[1].contours().len(), + "Masters should have the same number of contours" + ); + + // Both outer contours should have the same number of points + let contour0_points: usize = layers[0] + .contours() + .values() + .map(|c| c.points().len()) + .sum(); + let contour1_points: usize = layers[1] + .contours() + .values() + .map(|c| c.points().len()) + .sum(); + assert_eq!( + contour0_points, contour1_points, + "Masters should have the same total point count" + ); +} + +// --- Designspace (.designspace) tests --- + +fn mutatorsans_designspace_path() -> PathBuf { + fixtures_path().join("fonts/mutatorsans-variable/MutatorSans.designspace") +} + +#[test] +fn test_designspace_loads() { + let path = mutatorsans_designspace_path(); + let loader = FontLoader::new(); + let font = loader + .read_font(path.to_str().unwrap()) + .expect("Failed to load designspace"); + + assert!(font.is_variable(), "Designspace font should be variable"); + assert!( + font.glyph_count() > 10, + "MutatorSans should have many glyphs" + ); +} + +#[test] +fn test_designspace_axes() { + let path = mutatorsans_designspace_path(); + let loader = FontLoader::new(); + let font = loader.read_font(path.to_str().unwrap()).unwrap(); + + let axes = font.axes(); + assert_eq!(axes.len(), 2, "MutatorSans has width + weight axes"); + assert_eq!(axes[0].tag(), "wdth"); + assert_eq!(axes[0].name(), "width"); + assert_eq!(axes[0].minimum(), 0.0); + assert_eq!(axes[0].maximum(), 1000.0); + assert_eq!(axes[1].tag(), "wght"); + assert_eq!(axes[1].name(), "weight"); +} + +#[test] +fn test_designspace_sources() { + let path = mutatorsans_designspace_path(); + let loader = FontLoader::new(); + let font = loader.read_font(path.to_str().unwrap()).unwrap(); + + let sources = font.sources(); + // 4 main masters + 3 support layer sources = 7 + assert_eq!( + sources.len(), + 7, + "Should have 7 sources (4 masters + 3 support)" + ); + + // Default source (LightCondensed) at (0, 0) + let default = &sources[0]; + assert_eq!(default.location().get("wdth"), Some(0.0)); + assert_eq!(default.location().get("wght"), Some(0.0)); + assert!(default.filename().is_some()); +} + +#[test] +fn test_designspace_glyph_has_multiple_layers() { + let path = mutatorsans_designspace_path(); + let loader = FontLoader::new(); + let font = loader.read_font(path.to_str().unwrap()).unwrap(); + + let glyph_a = font.glyph("A").expect("Glyph 'A' should exist"); + // At least 4 layers from the 4 main masters + assert!( + glyph_a.layers().len() >= 4, + "Glyph A should have at least 4 layers, got {}", + glyph_a.layers().len() + ); +} + +#[test] +fn test_designspace_metadata_from_default_source() { + let path = mutatorsans_designspace_path(); + let loader = FontLoader::new(); + let font = loader.read_font(path.to_str().unwrap()).unwrap(); + + let metadata = font.metadata(); + assert_eq!( + metadata.family_name.as_deref(), + Some("MutatorMathTest"), + "Family name should come from designspace source" + ); +} diff --git a/crates/shift-core/tests/interpolation_parity.rs b/crates/shift-core/tests/interpolation_parity.rs new file mode 100644 index 00000000..1234f0c1 --- /dev/null +++ b/crates/shift-core/tests/interpolation_parity.rs @@ -0,0 +1,206 @@ +//! Parity-test fixture writer. +//! +//! Loads the real MutatorSans designspace, builds variation data for a glyph, +//! computes the expected interpolated values via fontdrasil at a known target, +//! and writes a JSON fixture for the TS parity test (in +//! `apps/desktop/src/renderer/src/lib/interpolation/interpolate.test.ts`) to +//! read back and assert the TS port agrees to within f64 precision. +//! +//! Run: `cargo test -p shift-core --test interpolation_parity`. + +use std::collections::{BTreeMap, HashMap}; +use std::fs; +use std::path::PathBuf; +use std::str::FromStr; + +use fontdrasil::coords::NormalizedLocation; +use fontdrasil::types::Tag; +use fontdrasil::variations::VariationModel; +use serde::Serialize; + +use shift_core::font_loader::FontLoader; +use shift_core::interpolation::{ + build_master_snapshots, get_glyph_variation_data, GlyphVariationData, +}; +use shift_core::snapshot::GlyphGeometry; +use shift_ir::variation::to_fd_location; +use shift_ir::Location; + +fn workspace_root() -> PathBuf { + PathBuf::from(env!("CARGO_MANIFEST_DIR")) + .parent() + .unwrap() + .parent() + .unwrap() + .to_path_buf() +} + +fn fixture_designspace() -> PathBuf { + workspace_root().join("fixtures/fonts/mutatorsans-variable/MutatorSans.designspace") +} + +fn fixture_output() -> PathBuf { + workspace_root().join("packages/types/__fixtures__/variation_parity.json") +} + +/// Local copy of the `flatten` walk used by `get_glyph_variation_data`. +/// Kept private to the test so production `flatten` can stay private. +/// Order MUST match shift-core::interpolation::flatten exactly. +fn flatten_geometry(g: &GlyphGeometry) -> Vec { + let mut v = vec![g.x_advance]; + for c in &g.contours { + for p in &c.points { + v.push(p.x); + v.push(p.y); + } + } + for a in &g.anchors { + v.push(a.x); + v.push(a.y); + } + v +} + +#[derive(Serialize)] +#[serde(rename_all = "camelCase")] +struct MasterEntry { + source_name: String, + is_default_source: bool, + designspace_location: BTreeMap, + normalised_location: BTreeMap, + /// Flat values at this master, in `flatten()` order. + /// `interpolate(data, normalisedLocation)` must equal this within 1e-9. + expected: Vec, +} + +#[derive(Serialize)] +#[serde(rename_all = "camelCase")] +struct Fixture { + /// For diagnostics — which glyph we sampled. + glyph_name: String, + + /// Mid-designspace target (for the headline parity assertion). + designspace_target: BTreeMap, + normalised_location: BTreeMap, + + /// What the TS `interpolate()` consumes — same shape Rust ships over NAPI. + data: GlyphVariationData, + + /// Ground truth from fontdrasil's `interpolate_from_deltas` at the mid target. + /// TS port must match within ~1e-9. + expected: Vec, + + /// Per-master round-trip data: at each master's location, interpolation must + /// recover that master's exact flat values. Catches unpacking drift between + /// Rust's flatten() and TS's applyValues walk. + masters: Vec, +} + +#[test] +fn write_parity_fixture() { + let designspace = fixture_designspace(); + let loader = FontLoader::new(); + let font = loader + .read_font(designspace.to_str().unwrap()) + .expect("load MutatorSans designspace"); + + // "A" is present in all four corner masters of MutatorSans — safe choice. + const GLYPH: &str = "A"; + let glyph = font.glyph(GLYPH).expect("glyph A missing"); + + let masters = build_master_snapshots(&font, glyph).expect("not variable / no masters"); + assert!( + masters.len() >= 4, + "expected ≥ 4 masters for A, got {}", + masters.len() + ); + + let axes = font.axes(); + let data = get_glyph_variation_data(&masters, axes).expect("variation data"); + + // Pick a non-trivial target — middle of designspace on each axis. + let mut target = Location::new(); + for axis in axes { + let mid = (axis.minimum() + axis.maximum()) / 2.0; + target.set(axis.tag().to_string(), mid); + } + let target_norm = to_fd_location(&target, axes); + + // Compute expected via fontdrasil directly — this is the ground truth. + let ordered_axes: Vec = axes + .iter() + .filter_map(|a| Tag::from_str(a.tag()).ok()) + .collect(); + + let mut points: HashMap> = HashMap::new(); // fontdrasil API takes HashMap + for m in &masters { + let loc = to_fd_location(&m.location, axes); + points.insert(loc, flatten_geometry(&m.geometry)); + } + let model = VariationModel::new(points.keys().cloned().collect(), ordered_axes); + let model_deltas = model.deltas::(&points).expect("compute deltas"); + let expected: Vec = model.interpolate_from_deltas(&target_norm, &model_deltas); + + let designspace_target: BTreeMap = target + .iter() + .map(|(tag, value)| (tag.clone(), *value)) + .collect(); + let normalised_location: BTreeMap = target_norm + .iter() + .map(|(tag, coord)| (tag.to_string(), coord.into_inner().into_inner())) + .collect(); + + // Per-master round-trip data — at each master's location, interpolation + // must equal that master's flat values. + let master_entries: Vec = masters + .iter() + .map(|m| { + let m_norm = to_fd_location(&m.location, axes); + let m_expected = model.interpolate_from_deltas(&m_norm, &model_deltas); + MasterEntry { + source_name: m.source_name.clone(), + is_default_source: m.is_default_source, + designspace_location: m + .location + .iter() + .map(|(k, v)| (k.clone(), *v)) + .collect::>(), + normalised_location: m_norm + .iter() + .map(|(t, c)| (t.to_string(), c.into_inner().into_inner())) + .collect::>(), + expected: m_expected, + } + }) + .collect(); + + let fixture = Fixture { + glyph_name: GLYPH.to_string(), + designspace_target, + normalised_location, + data, + expected, + masters: master_entries, + }; + + let out = fixture_output(); + // Trailing newline to match what pre-commit's end-of-file-fixer expects; + // without it the fixer would re-add it, breaking idempotency on re-runs. + let new_json = format!("{}\n", serde_json::to_string_pretty(&fixture).unwrap()); + + // Idempotent: only write when content actually changes. This keeps the + // fixture stable across CI runs and pre-commit hooks (which run cargo + // test) — without it, every run would rewrite the file and the hook + // would flag "files modified after staging." + let needs_write = match fs::read_to_string(&out) { + Ok(existing) => existing != new_json, + Err(_) => true, + }; + if needs_write { + fs::create_dir_all(out.parent().unwrap()).expect("mkdir __fixtures__"); + fs::write(&out, &new_json).expect("write fixture"); + println!("wrote parity fixture → {}", out.display()); + } else { + println!("parity fixture up to date ({})", out.display()); + } +} diff --git a/crates/shift-core/tests/round_trip.rs b/crates/shift-core/tests/round_trip.rs index d729795d..98fdaa5d 100644 --- a/crates/shift-core/tests/round_trip.rs +++ b/crates/shift-core/tests/round_trip.rs @@ -755,12 +755,11 @@ fn test_ufo_round_trip_layer_glyph_counts() { } } - let reload_layer = reloaded + let (&reload_layer_id, _) = reloaded .layers() - .values() - .find(|l| l.name() == orig_name) + .iter() + .find(|(_, l)| l.name() == orig_name) .unwrap_or_else(|| panic!("Layer '{orig_name}' should exist")); - let reload_layer_id = reload_layer.id(); let mut reload_glyph_count = 0; for glyph in reloaded.glyphs().values() { diff --git a/crates/shift-ir/Cargo.toml b/crates/shift-ir/Cargo.toml index b3adb4a7..706c6f48 100644 --- a/crates/shift-ir/Cargo.toml +++ b/crates/shift-ir/Cargo.toml @@ -9,6 +9,8 @@ license = "MIT OR Apache-2.0" crate-type = ["rlib"] [dependencies] +fontdrasil = "0.4.0" +indexmap = { version = "2", features = ["serde"] } kurbo = "0.13.0" linesweeper = "0.3.0" serde = { version = "1.0", features = ["derive"] } diff --git a/crates/shift-ir/src/axis.rs b/crates/shift-ir/src/axis.rs index 75cc3d20..d7b5bdfc 100644 --- a/crates/shift-ir/src/axis.rs +++ b/crates/shift-ir/src/axis.rs @@ -1,7 +1,10 @@ use serde::{Deserialize, Serialize}; use std::collections::HashMap; +use ts_rs::TS; -#[derive(Clone, Debug, Serialize, Deserialize)] +#[derive(Clone, Debug, Serialize, Deserialize, TS)] +#[serde(rename_all = "camelCase")] +#[ts(export, export_to = "../../../packages/types/src/generated/")] pub struct Axis { tag: String, name: String, @@ -94,7 +97,8 @@ impl Axis { } } -#[derive(Clone, Debug, Default, Serialize, Deserialize)] +#[derive(Clone, Debug, Default, Serialize, Deserialize, TS)] +#[ts(export, export_to = "../../../packages/types/src/generated/")] pub struct Location { values: HashMap, } @@ -133,6 +137,13 @@ impl Location { } Location::from_map(normalized) } + + pub fn is_default_axis(&self, axes: &[Axis]) -> bool { + axes.iter().all(|axis| { + let value = self.get(axis.tag()).unwrap_or(axis.default()); + (value - axis.default()).abs() < f64::EPSILON + }) + } } #[cfg(test)] diff --git a/crates/shift-ir/src/font.rs b/crates/shift-ir/src/font.rs index 974f38a9..85d95a2f 100644 --- a/crates/shift-ir/src/font.rs +++ b/crates/shift-ir/src/font.rs @@ -1,5 +1,5 @@ use crate::axis::Axis; -use crate::entity::LayerId; +use crate::entity::{LayerId, SourceId}; use crate::features::FeatureData; use crate::glyph::Glyph; use crate::guideline::Guideline; @@ -83,6 +83,8 @@ pub struct Font { metrics: FontMetrics, axes: Vec, sources: Vec, + #[serde(default)] + default_source_id: Option, layers: HashMap, glyphs: HashMap, kerning: KerningData, @@ -103,6 +105,7 @@ impl Default for Font { metrics: FontMetrics::default(), axes: Vec::new(), sources: Vec::new(), + default_source_id: None, layers, glyphs: HashMap::new(), kerning: KerningData::new(), @@ -147,8 +150,28 @@ impl Font { &self.sources } - pub fn add_source(&mut self, source: Source) { + pub fn add_source(&mut self, source: Source) -> SourceId { + let source_id = source.id(); + if self.default_source_id.is_none() { + self.default_source_id = Some(source_id); + } self.sources.push(source); + source_id + } + + pub fn default_source_id(&self) -> Option { + self.default_source_id + } + + pub fn set_default_source_id(&mut self, source_id: SourceId) { + self.default_source_id = Some(source_id); + } + + pub fn default_source(&self) -> Option<&Source> { + let default_source_id = self.default_source_id?; + self.sources + .iter() + .find(|source| source.id() == default_source_id) } pub fn is_variable(&self) -> bool { diff --git a/crates/shift-ir/src/glyph.rs b/crates/shift-ir/src/glyph.rs index 28f05fd5..6363c0e4 100644 --- a/crates/shift-ir/src/glyph.rs +++ b/crates/shift-ir/src/glyph.rs @@ -5,6 +5,7 @@ use crate::entity::{AnchorId, ComponentId, ContourId, GlyphId, LayerId}; use crate::guideline::Guideline; use crate::lib_data::LibData; use crate::GlyphName; +use indexmap::IndexMap; use serde::{Deserialize, Serialize}; use std::collections::HashMap; @@ -21,7 +22,7 @@ pub struct Glyph { pub struct GlyphLayer { width: f64, height: Option, - contours: HashMap, + contours: IndexMap, components: HashMap, anchors: Vec, guidelines: Vec, @@ -56,7 +57,7 @@ impl GlyphLayer { self.height = height; } - pub fn contours(&self) -> &HashMap { + pub fn contours(&self) -> &IndexMap { &self.contours } @@ -79,7 +80,7 @@ impl GlyphLayer { } pub fn remove_contour(&mut self, id: ContourId) -> Option { - self.contours.remove(&id) + self.contours.shift_remove(&id) } pub fn clear_contours(&mut self) { diff --git a/crates/shift-ir/src/lib.rs b/crates/shift-ir/src/lib.rs index a4e911c4..b22c658f 100644 --- a/crates/shift-ir/src/lib.rs +++ b/crates/shift-ir/src/lib.rs @@ -15,6 +15,7 @@ mod metrics; mod point; mod segment; mod source; +pub mod variation; pub use anchor::Anchor; pub use axis::{Axis, Location}; diff --git a/crates/shift-ir/src/source.rs b/crates/shift-ir/src/source.rs index bbe49a6a..aa593e29 100644 --- a/crates/shift-ir/src/source.rs +++ b/crates/shift-ir/src/source.rs @@ -1,12 +1,17 @@ use crate::axis::Location; use crate::entity::{LayerId, SourceId}; use serde::{Deserialize, Serialize}; +use ts_rs::TS; -#[derive(Clone, Debug, Serialize, Deserialize)] +#[derive(Clone, Debug, Serialize, Deserialize, TS)] +#[serde(rename_all = "camelCase")] +#[ts(export, export_to = "../../../packages/types/src/generated/")] pub struct Source { + #[ts(type = "string")] id: SourceId, name: String, location: Location, + #[ts(type = "string")] layer_id: LayerId, filename: Option, } diff --git a/crates/shift-ir/src/variation.rs b/crates/shift-ir/src/variation.rs new file mode 100644 index 00000000..59851249 --- /dev/null +++ b/crates/shift-ir/src/variation.rs @@ -0,0 +1,24 @@ +use std::str::FromStr; + +use fontdrasil::{ + coords::{NormalizedCoord, NormalizedLocation}, + types::Tag, +}; + +use crate::{Axis, Location}; + +pub fn to_fd_location(loc: &Location, axes: &[Axis]) -> NormalizedLocation { + let mut result = NormalizedLocation::new(); + + for axis in axes { + let value = loc.get(axis.tag()).unwrap_or(axis.default()); + let n = axis.normalize(value); + let Ok(tag) = Tag::from_str(axis.tag()) else { + continue; + }; + + result.insert(tag, NormalizedCoord::new(n)); + } + + result +} diff --git a/crates/shift-node/__test__/font_integration.spec.mjs b/crates/shift-node/__test__/font_integration.spec.mjs index d239cd23..e6d08828 100644 --- a/crates/shift-node/__test__/font_integration.spec.mjs +++ b/crates/shift-node/__test__/font_integration.spec.mjs @@ -23,7 +23,6 @@ function startEditSessionByUnicode(engine, unicode) { describe("FontEngine Integration - UFO Loading", () => { it("loads MutatorSans UFO successfully", () => { if (!existsSync(MUTATORSANS_UFO)) { - console.log("Skipping: MutatorSans UFO not found"); return; } @@ -232,7 +231,6 @@ describe("FontEngine Integration - Round Trip", () => { describe("FontEngine Integration - TTF Loading", () => { it("loads MutatorSans TTF successfully", () => { if (!existsSync(MUTATORSANS_TTF)) { - console.log("Skipping: MutatorSans TTF not found"); return; } @@ -499,3 +497,166 @@ describe("FontEngine Integration - Extended Round Trip", () => { expect(reloadedTypes).toEqual(originalTypes); }); }); + +// --- Variable font (.glyphs with multiple masters) tests --- + +const MUTATORSANS_VARIABLE = join(FIXTURES_PATH, "fonts/MutatorSansVariable.glyphs"); + +describe("FontEngine Integration - Variable Font (.glyphs)", () => { + it("detects variable font", () => { + const engine = new FontEngine(); + engine.loadFont(MUTATORSANS_VARIABLE); + expect(engine.isVariable()).toBe(true); + }); + + it("returns axes", () => { + const engine = new FontEngine(); + engine.loadFont(MUTATORSANS_VARIABLE); + const axes = JSON.parse(engine.getAxes()); + expect(axes).toHaveLength(1); + expect(axes[0].tag).toBe("wght"); + expect(axes[0].name).toBe("Weight"); + expect(axes[0].minimum).toBe(100); + expect(axes[0].maximum).toBe(900); + expect(axes[0].default).toBe(100); + }); + + it("returns sources", () => { + const engine = new FontEngine(); + engine.loadFont(MUTATORSANS_VARIABLE); + const sources = JSON.parse(engine.getSources()); + expect(sources).toHaveLength(2); + expect(sources[0].location.values.wght).toBe(100); + expect(sources[1].location.values.wght).toBe(900); + }); + + it("returns master snapshots for glyph A", () => { + const engine = new FontEngine(); + engine.loadFont(MUTATORSANS_VARIABLE); + const json = engine.getGlyphMasterSnapshots("A"); + expect(json).not.toBeNull(); + const masters = JSON.parse(json); + expect(masters).toHaveLength(2); + + // Each master snapshot carries source metadata plus interpolation geometry. + for (const m of masters) { + expect(m).toHaveProperty("sourceId"); + expect(m).toHaveProperty("sourceName"); + expect(m).toHaveProperty("location"); + expect(m).toHaveProperty("isDefaultSource"); + expect(m).toHaveProperty("geometry"); + expect(m).not.toHaveProperty("snapshot"); + expect(m.geometry.contours).toHaveLength(2); + expect(m.geometry.xAdvance).toBeGreaterThan(0); + } + + // Both masters should have matching total point counts + const lightTotal = masters[0].geometry.contours.reduce((s, c) => s + c.points.length, 0); + const boldTotal = masters[1].geometry.contours.reduce((s, c) => s + c.points.length, 0); + expect(lightTotal).toBe(boldTotal); + }); + + it("non-variable font returns isVariable false", () => { + const engine = new FontEngine(); + engine.loadFont(MUTATORSANS_UFO); + expect(engine.isVariable()).toBe(false); + }); + + it("returns null for non-existent glyph master snapshots", () => { + const engine = new FontEngine(); + engine.loadFont(MUTATORSANS_VARIABLE); + const json = engine.getGlyphMasterSnapshots("nonexistent"); + expect(json).toBeNull(); + }); +}); + +// --- Designspace (.designspace) tests --- + +const MUTATORSANS_DESIGNSPACE = join( + FIXTURES_PATH, + "fonts/mutatorsans-variable/MutatorSans.designspace", +); + +describe("FontEngine Integration - Designspace", () => { + it("loads designspace and detects variable font", () => { + const engine = new FontEngine(); + engine.loadFont(MUTATORSANS_DESIGNSPACE); + expect(engine.isVariable()).toBe(true); + expect(engine.getGlyphCount()).toBeGreaterThan(10); + }); + + it("returns axes from designspace", () => { + const engine = new FontEngine(); + engine.loadFont(MUTATORSANS_DESIGNSPACE); + const axes = JSON.parse(engine.getAxes()); + expect(axes).toHaveLength(2); + expect(axes[0].tag).toBe("wdth"); + expect(axes[0].minimum).toBe(0); + expect(axes[0].maximum).toBe(1000); + expect(axes[1].tag).toBe("wght"); + }); + + it("returns sources from designspace", () => { + const engine = new FontEngine(); + engine.loadFont(MUTATORSANS_DESIGNSPACE); + const sources = JSON.parse(engine.getSources()); + // 4 main masters + 3 support layers + expect(sources).toHaveLength(7); + expect(sources[0].location.values.wdth).toBe(0); + expect(sources[0].location.values.wght).toBe(0); + }); + + it("returns master snapshots for glyph A", () => { + const engine = new FontEngine(); + engine.loadFont(MUTATORSANS_DESIGNSPACE); + const json = engine.getGlyphMasterSnapshots("A"); + expect(json).not.toBeNull(); + const masters = JSON.parse(json); + expect(masters.length).toBeGreaterThanOrEqual(4); + expect(masters.filter((m) => m.isDefaultSource)).toHaveLength(1); + for (const m of masters) { + expect(m).toHaveProperty("geometry"); + expect(m).not.toHaveProperty("snapshot"); + expect(m.geometry.contours.length).toBeGreaterThan(0); + expect(m.geometry.xAdvance).toBeGreaterThan(0); + } + }); + + it("excludes empty contours from master snapshots", () => { + const engine = new FontEngine(); + engine.loadFont(MUTATORSANS_DESIGNSPACE); + const json = engine.getGlyphMasterSnapshots("A"); + const masters = JSON.parse(json); + for (const m of masters) { + for (const contour of m.geometry.contours) { + expect(contour.points.length).toBeGreaterThan(0); + } + } + }); + + it("returns consistent contour order across masters", () => { + const engine = new FontEngine(); + engine.loadFont(MUTATORSANS_DESIGNSPACE); + const json = engine.getGlyphMasterSnapshots("A"); + const masters = JSON.parse(json); + + // All masters should have the same contour signature (point counts per contour) + const sigs = masters.map((m) => m.geometry.contours.map((c) => c.points.length).join(",")); + const uniqueSigs = new Set(sigs); + expect(uniqueSigs.size).toBe(1); + }); + + it("returns master snapshots for the currently editing glyph", () => { + const engine = new FontEngine(); + engine.loadFont(MUTATORSANS_DESIGNSPACE); + engine.startEditSession({ glyphName: "A", unicode: 65 }); + + // Glyph is taken from font during session, but snapshots should still work + const json = engine.getGlyphMasterSnapshots("A"); + expect(json).not.toBeNull(); + const masters = JSON.parse(json); + expect(masters.length).toBeGreaterThanOrEqual(4); + + engine.endEditSession(); + }); +}); diff --git a/crates/shift-node/index.d.ts b/crates/shift-node/index.d.ts index c2525d2b..048a6d72 100644 --- a/crates/shift-node/index.d.ts +++ b/crates/shift-node/index.d.ts @@ -19,6 +19,12 @@ export declare class FontEngine { getGlyphAdvanceByName(glyphName: string): number | null getGlyphBboxByName(glyphName: string): Array | null getGlyphCompositeComponents(glyphName: string): string | null + isVariable(): boolean + getAxes(): string + getSources(): string + /** Returns a JSON array of master snapshots for a glyph. */ + getGlyphMasterSnapshots(glyphName: string): string | null + getGlyphVariationData(glyphName: string): string | null startEditSession(glyphRef: JsGlyphRef): void endEditSession(): void hasEditSession(): boolean diff --git a/crates/shift-node/src/font_engine.rs b/crates/shift-node/src/font_engine.rs index 9b2f9a69..142af615 100644 --- a/crates/shift-node/src/font_engine.rs +++ b/crates/shift-node/src/font_engine.rs @@ -1,16 +1,17 @@ use napi::bindgen_prelude::*; use napi::{Error, Result, Status}; use napi_derive::napi; +use shift_core::interpolation::get_glyph_variation_data; use shift_core::{ composite::{ flatten_component_contours_for_layer as flatten_component_contours, layer_bbox, - layer_complexity, layer_to_svg_path, preferred_layer_for_glyph, - resolve_component_instances_for_layer, resolved_to_render_contours, GlyphLayerProvider, + layer_to_svg_path, resolve_component_instances_for_layer, resolved_to_render_contours, + GlyphLayerProvider, }, dependency_graph::DependencyGraph, edit_session::EditSession, font_loader::FontLoader, - snapshot::{CommandResult, GlyphSnapshot, RenderContourSnapshot}, + snapshot::{CommandResult, GlyphSnapshot, MasterSnapshot, RenderContourSnapshot}, AnchorId, BooleanOp, ContourId, Font, FontWriter, Glyph, GlyphLayer, GuidelineId, LayerId, NodePositionUpdate, NodeRef, PasteContour, PointId, PointType, UfoWriter, }; @@ -59,10 +60,8 @@ impl GlyphLayerProvider for EngineLayerProvider<'_> { } } - self - .font - .glyph(glyph_name) - .and_then(preferred_layer_for_glyph) + let glyph = self.font.glyph(glyph_name)?; + glyph.layer(self.font.default_layer_id()) } } @@ -233,6 +232,10 @@ impl FontEngine { } } + fn default_layer_for_glyph<'a>(&'a self, glyph: &'a Glyph) -> Option<&'a GlyphLayer> { + glyph.layer(self.font.default_layer_id()) + } + fn editing_target_for_unicode(&self, unicode: u32) -> Option<(&str, &GlyphLayer)> { if let Some(session) = &self.current_edit_session { if session.unicode() == unicode { @@ -249,7 +252,7 @@ impl FontEngine { } let glyph = self.font.glyph_by_unicode(unicode)?; - let layer = preferred_layer_for_glyph(glyph)?; + let layer = self.default_layer_for_glyph(glyph)?; composite_debug!( "editing_target_for_unicode U+{:04X}: from font glyph='{}' (contours={}, components={}, anchors={})", unicode, @@ -269,7 +272,7 @@ impl FontEngine { } let glyph = self.font.glyph(glyph_name)?; - let layer = preferred_layer_for_glyph(glyph)?; + let layer = self.default_layer_for_glyph(glyph)?; Some((glyph.name(), layer)) } @@ -280,10 +283,8 @@ impl FontEngine { } } - self - .font - .glyph(glyph_name) - .and_then(preferred_layer_for_glyph) + let glyph = self.font.glyph(glyph_name)?; + self.default_layer_for_glyph(glyph) } fn flatten_component_contours_for_layer( @@ -481,6 +482,62 @@ impl FontEngine { })) } + #[napi] + pub fn is_variable(&self) -> bool { + self.font.is_variable() + } + + #[napi] + pub fn get_axes(&self) -> String { + to_json(&self.font.axes()) + } + + #[napi] + pub fn get_sources(&self) -> String { + to_json(&self.font.sources()) + } + + /// Returns a JSON array of master snapshots for a glyph. + #[napi] + pub fn get_glyph_master_snapshots(&self, glyph_name: String) -> Option { + let masters = self.build_master_snapshots(&glyph_name)?; + Some(to_json(&masters)) + } + + #[napi] + pub fn get_glyph_variation_data(&self, glyph_name: String) -> Option { + let masters = self.build_master_snapshots(&glyph_name)?; + let axes = self.font.axes(); + let variation_data = get_glyph_variation_data(&masters, axes)?; + + Some(to_json(&variation_data)) + } + + fn build_master_snapshots(&self, glyph_name: &str) -> Option> { + let editing = self.editing_glyph_for(glyph_name); + let glyph: &Glyph = match &editing { + Some(g) => g, + None => self.font.glyph(glyph_name)?, + }; + shift_core::interpolation::build_master_snapshots(&self.font, glyph) + } + + /// If the glyph currently being edited is `glyph_name`, return a copy with the + /// in-progress session layer patched in. Otherwise `None` — caller falls back + /// to the disk copy. + fn editing_glyph_for(&self, glyph_name: &str) -> Option { + let editing = self.editing_glyph.as_ref()?; + if editing.name() != glyph_name { + return None; + } + let session = self.current_edit_session.as_ref()?; + let layer_id = *self.editing_layer_id.as_ref()?; + + let mut temp = editing.clone(); + temp.set_layer(layer_id, session.layer().clone()); + Some(temp) + } + // ═══════════════════════════════════════════════════════════ // EDIT SESSIONS // ═══════════════════════════════════════════════════════════ @@ -516,19 +573,16 @@ impl FontEngine { glyph.layers().len(), primary_unicode ); - let (layer_id, layer) = glyph - .layers() - .iter() - .max_by_key(|(_, l)| layer_complexity(l)) - .map(|(id, _)| *id) - .and_then(|id| glyph.remove_layer(id).map(|l| (id, l))) - .unwrap_or_else(|| (self.font.default_layer_id(), GlyphLayer::with_width(500.0))); + let default_layer_id = self.font.default_layer_id(); + let layer = glyph + .remove_layer(default_layer_id) + .unwrap_or_else(|| GlyphLayer::with_width(500.0)); let edit_session = EditSession::new(glyph.name().to_string(), primary_unicode, layer); self.current_edit_session = Some(edit_session); self.editing_glyph = Some(glyph); - self.editing_layer_id = Some(layer_id); + self.editing_layer_id = Some(default_layer_id); Ok(()) } diff --git a/fixtures/fonts/MutatorSansVariable.glyphs b/fixtures/fonts/MutatorSansVariable.glyphs new file mode 100644 index 00000000..e5b09fe3 --- /dev/null +++ b/fixtures/fonts/MutatorSansVariable.glyphs @@ -0,0 +1,143 @@ +{ +.appVersion = "1225"; +familyName = MutatorSans; +axes = ( +{ +name = Weight; +tag = wght; +} +); +fontMaster = ( +{ +ascender = 800; +capHeight = 700; +descender = -200; +id = master-light; +customName = Light; +weightValue = 100; +xHeight = 500; +}, +{ +ascender = 800; +capHeight = 700; +descender = -200; +id = master-bold; +customName = Bold; +weightValue = 900; +xHeight = 500; +} +); +glyphs = ( +{ +glyphname = A; +unicode = 0041; +layers = ( +{ +layerId = master-light; +width = 500; +paths = ( +{ +closed = 1; +nodes = ( +"0 0 LINE", +"200 700 LINE", +"250 700 LINE", +"450 0 LINE", +"375 0 LINE", +"325 200 LINE", +"125 200 LINE", +"75 0 LINE" +); +}, +{ +closed = 1; +nodes = ( +"150 270 LINE", +"300 270 LINE", +"225 560 LINE" +); +} +); +}, +{ +layerId = master-bold; +width = 600; +paths = ( +{ +closed = 1; +nodes = ( +"0 0 LINE", +"180 700 LINE", +"320 700 LINE", +"500 0 LINE", +"380 0 LINE", +"330 200 LINE", +"170 200 LINE", +"120 0 LINE" +); +}, +{ +closed = 1; +nodes = ( +"200 270 LINE", +"300 270 LINE", +"250 520 LINE" +); +} +); +} +); +}, +{ +glyphname = space; +unicode = 0020; +layers = ( +{ +layerId = master-light; +width = 250; +}, +{ +layerId = master-bold; +width = 300; +} +); +}, +{ +glyphname = I; +unicode = 0049; +layers = ( +{ +layerId = master-light; +width = 200; +paths = ( +{ +closed = 1; +nodes = ( +"50 0 LINE", +"50 700 LINE", +"100 700 LINE", +"100 0 LINE" +); +} +); +}, +{ +layerId = master-bold; +width = 300; +paths = ( +{ +closed = 1; +nodes = ( +"50 0 LINE", +"50 700 LINE", +"200 700 LINE", +"200 0 LINE" +); +} +); +} +); +} +); +unitsPerEm = 1000; +} diff --git a/fixtures/fonts/mutatorsans-variable/LICENSE b/fixtures/fonts/mutatorsans-variable/LICENSE new file mode 100644 index 00000000..affdc0ee --- /dev/null +++ b/fixtures/fonts/mutatorsans-variable/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2017 Erik van Blokland + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/fixtures/fonts/mutatorsans-variable/MutatorSans.designspace b/fixtures/fonts/mutatorsans-variable/MutatorSans.designspace new file mode 100644 index 00000000..fc76d7db --- /dev/null +++ b/fixtures/fonts/mutatorsans-variable/MutatorSans.designspace @@ -0,0 +1,325 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + com.letterror.designspaceEditor.previewLocation + + weight + 146.73033142089844 + width + 58.626346588134766 + + com.letterror.designspaceEditor.previewText + FISH + com.letterror.longboard.interactionSources + + + width + horizontal + + + weight + vertical + + + com.letterror.mathModelPref + previewMutatorMath + com.letterror.skateboard.interactionSources + + horizontal + + width + + ignore + + vertical + + weight + + + com.letterror.skateboard.interestingLocation + + + + weight + 775.609 + width + 794.522 + + S1 + + + + weight + 855.549 + width + 795.978 + + S2 + + + + weight + 1194.939375384999 + width + 898.8087507107668 + + S3 + + + + weight + 161.67457510442006 + width + 404.05720203707176 + + This is horrible + + + + weight + 467.73409948979594 + width + 538.7016581632644 + + Stem == 200? + + + + weight + 658.597 + width + 93.05199999999985 + + My_new_location + + + com.letterror.skateboard.previewLocation + + weight + 177.33442834877678 + width + 747.3306156281592 + + com.superpolator.data + + axiscolors + + weight + + 0.5 + 0.5 + 0.5 + 1.0 + + width + + 0.5 + 0.5 + 0.5 + 1.0 + + + instancefolder + instances + lineInverted + + lineStacked + sequence + lineViewFilled + + previewtext + SUPER + snippets + + + designspaceEdit.notes + + + + diff --git a/fixtures/fonts/mutatorsans-variable/MutatorSansBoldCondensed.ufo/features.fea b/fixtures/fonts/mutatorsans-variable/MutatorSansBoldCondensed.ufo/features.fea new file mode 100644 index 00000000..f5f829a8 --- /dev/null +++ b/fixtures/fonts/mutatorsans-variable/MutatorSansBoldCondensed.ufo/features.fea @@ -0,0 +1,3 @@ +# this is the feature from boldcondensed. +languagesystem DFLT dflt; +languagesystem latn dflt; diff --git a/fixtures/fonts/mutatorsans-variable/MutatorSansBoldCondensed.ufo/fontinfo.plist b/fixtures/fonts/mutatorsans-variable/MutatorSansBoldCondensed.ufo/fontinfo.plist new file mode 100644 index 00000000..eba66dec --- /dev/null +++ b/fixtures/fonts/mutatorsans-variable/MutatorSansBoldCondensed.ufo/fontinfo.plist @@ -0,0 +1,68 @@ + + + + + ascender + 800 + capHeight + 800 + copyright + License same as MutatorMath. BSD 3-clause. [test-token: A] + descender + -200 + familyName + MutatorSans + guidelines + + italicAngle + 0 + openTypeNameLicense + License same as MutatorMath. BSD 3-clause. [test-token: A] + openTypeOS2VendorID + LTTR + postscriptBlueValues + + -10 + 0 + 800 + 810 + + postscriptDefaultWidthX + 500 + postscriptFamilyBlues + + postscriptFamilyOtherBlues + + postscriptFontName + MutatorSans-BoldCondensed + postscriptOtherBlues + + 500 + 520 + + postscriptSlantAngle + 0 + postscriptStemSnapH + + postscriptStemSnapV + + postscriptWindowsCharacterSet + 1 + styleMapFamilyName + + styleMapStyleName + regular + styleName + BoldCondensed + unitsPerEm + 1000 + versionMajor + 1 + versionMinor + 2 + xHeight + 500 + year + 2004 + + diff --git a/fixtures/fonts/mutatorsans-variable/MutatorSansBoldCondensed.ufo/glyphs.background/S_.closed.glif b/fixtures/fonts/mutatorsans-variable/MutatorSansBoldCondensed.ufo/glyphs.background/S_.closed.glif new file mode 100644 index 00000000..12ce1bbc --- /dev/null +++ b/fixtures/fonts/mutatorsans-variable/MutatorSansBoldCondensed.ufo/glyphs.background/S_.closed.glif @@ -0,0 +1,52 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/fixtures/fonts/mutatorsans-variable/MutatorSansBoldCondensed.ufo/glyphs.background/contents.plist b/fixtures/fonts/mutatorsans-variable/MutatorSansBoldCondensed.ufo/glyphs.background/contents.plist new file mode 100644 index 00000000..0ef1afc6 --- /dev/null +++ b/fixtures/fonts/mutatorsans-variable/MutatorSansBoldCondensed.ufo/glyphs.background/contents.plist @@ -0,0 +1,8 @@ + + + + + S.closed + S_.closed.glif + + diff --git a/fixtures/fonts/mutatorsans-variable/MutatorSansBoldCondensed.ufo/glyphs.background/layerinfo.plist b/fixtures/fonts/mutatorsans-variable/MutatorSansBoldCondensed.ufo/glyphs.background/layerinfo.plist new file mode 100644 index 00000000..7e385c7f --- /dev/null +++ b/fixtures/fonts/mutatorsans-variable/MutatorSansBoldCondensed.ufo/glyphs.background/layerinfo.plist @@ -0,0 +1,8 @@ + + + + + color + 0.5,1,0,0.7 + + diff --git a/fixtures/fonts/mutatorsans-variable/MutatorSansBoldCondensed.ufo/glyphs/A_.glif b/fixtures/fonts/mutatorsans-variable/MutatorSansBoldCondensed.ufo/glyphs/A_.glif new file mode 100644 index 00000000..306d8ee3 --- /dev/null +++ b/fixtures/fonts/mutatorsans-variable/MutatorSansBoldCondensed.ufo/glyphs/A_.glif @@ -0,0 +1,43 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + com.typemytype.robofont.Image.Brightness + 0 + com.typemytype.robofont.Image.Contrast + 1 + com.typemytype.robofont.Image.Saturation + 1 + com.typemytype.robofont.Image.Sharpness + 0.4 + + + diff --git a/fixtures/fonts/mutatorsans-variable/MutatorSansBoldCondensed.ufo/glyphs/A_acute.glif b/fixtures/fonts/mutatorsans-variable/MutatorSansBoldCondensed.ufo/glyphs/A_acute.glif new file mode 100644 index 00000000..f0415223 --- /dev/null +++ b/fixtures/fonts/mutatorsans-variable/MutatorSansBoldCondensed.ufo/glyphs/A_acute.glif @@ -0,0 +1,15 @@ + + + + + + + + + + + public.markColor + 0.6567,0.6903,1,1 + + + diff --git a/fixtures/fonts/mutatorsans-variable/MutatorSansBoldCondensed.ufo/glyphs/A_dieresis.glif b/fixtures/fonts/mutatorsans-variable/MutatorSansBoldCondensed.ufo/glyphs/A_dieresis.glif new file mode 100644 index 00000000..7109f724 --- /dev/null +++ b/fixtures/fonts/mutatorsans-variable/MutatorSansBoldCondensed.ufo/glyphs/A_dieresis.glif @@ -0,0 +1,15 @@ + + + + + + + + + + + public.markColor + 0.6567,0.6903,1,1 + + + diff --git a/fixtures/fonts/mutatorsans-variable/MutatorSansBoldCondensed.ufo/glyphs/B_.glif b/fixtures/fonts/mutatorsans-variable/MutatorSansBoldCondensed.ufo/glyphs/B_.glif new file mode 100644 index 00000000..e22f432c --- /dev/null +++ b/fixtures/fonts/mutatorsans-variable/MutatorSansBoldCondensed.ufo/glyphs/B_.glif @@ -0,0 +1,53 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/fixtures/fonts/mutatorsans-variable/MutatorSansBoldCondensed.ufo/glyphs/C_.glif b/fixtures/fonts/mutatorsans-variable/MutatorSansBoldCondensed.ufo/glyphs/C_.glif new file mode 100644 index 00000000..284dcf64 --- /dev/null +++ b/fixtures/fonts/mutatorsans-variable/MutatorSansBoldCondensed.ufo/glyphs/C_.glif @@ -0,0 +1,51 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + com.typemytype.robofont.Image.Brightness + 0 + com.typemytype.robofont.Image.Contrast + 1 + com.typemytype.robofont.Image.Saturation + 1 + com.typemytype.robofont.Image.Sharpness + 0.4 + + + diff --git a/fixtures/fonts/mutatorsans-variable/MutatorSansBoldCondensed.ufo/glyphs/D_.glif b/fixtures/fonts/mutatorsans-variable/MutatorSansBoldCondensed.ufo/glyphs/D_.glif new file mode 100644 index 00000000..a1da8180 --- /dev/null +++ b/fixtures/fonts/mutatorsans-variable/MutatorSansBoldCondensed.ufo/glyphs/D_.glif @@ -0,0 +1,33 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/fixtures/fonts/mutatorsans-variable/MutatorSansBoldCondensed.ufo/glyphs/E_.glif b/fixtures/fonts/mutatorsans-variable/MutatorSansBoldCondensed.ufo/glyphs/E_.glif new file mode 100644 index 00000000..d127056b --- /dev/null +++ b/fixtures/fonts/mutatorsans-variable/MutatorSansBoldCondensed.ufo/glyphs/E_.glif @@ -0,0 +1,44 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + com.typemytype.robofont.Image.Brightness + 0 + com.typemytype.robofont.Image.Contrast + 1 + com.typemytype.robofont.Image.Saturation + 1 + com.typemytype.robofont.Image.Sharpness + 0.4 + + + diff --git a/fixtures/fonts/mutatorsans-variable/MutatorSansBoldCondensed.ufo/glyphs/F_.glif b/fixtures/fonts/mutatorsans-variable/MutatorSansBoldCondensed.ufo/glyphs/F_.glif new file mode 100644 index 00000000..8ed63e71 --- /dev/null +++ b/fixtures/fonts/mutatorsans-variable/MutatorSansBoldCondensed.ufo/glyphs/F_.glif @@ -0,0 +1,25 @@ + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/fixtures/fonts/mutatorsans-variable/MutatorSansBoldCondensed.ufo/glyphs/G_.glif b/fixtures/fonts/mutatorsans-variable/MutatorSansBoldCondensed.ufo/glyphs/G_.glif new file mode 100644 index 00000000..48fd1a19 --- /dev/null +++ b/fixtures/fonts/mutatorsans-variable/MutatorSansBoldCondensed.ufo/glyphs/G_.glif @@ -0,0 +1,48 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/fixtures/fonts/mutatorsans-variable/MutatorSansBoldCondensed.ufo/glyphs/H_.glif b/fixtures/fonts/mutatorsans-variable/MutatorSansBoldCondensed.ufo/glyphs/H_.glif new file mode 100644 index 00000000..e66768ac --- /dev/null +++ b/fixtures/fonts/mutatorsans-variable/MutatorSansBoldCondensed.ufo/glyphs/H_.glif @@ -0,0 +1,25 @@ + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/fixtures/fonts/mutatorsans-variable/MutatorSansBoldCondensed.ufo/glyphs/I_.glif b/fixtures/fonts/mutatorsans-variable/MutatorSansBoldCondensed.ufo/glyphs/I_.glif new file mode 100644 index 00000000..718d4872 --- /dev/null +++ b/fixtures/fonts/mutatorsans-variable/MutatorSansBoldCondensed.ufo/glyphs/I_.glif @@ -0,0 +1,25 @@ + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/fixtures/fonts/mutatorsans-variable/MutatorSansBoldCondensed.ufo/glyphs/I_.narrow.glif b/fixtures/fonts/mutatorsans-variable/MutatorSansBoldCondensed.ufo/glyphs/I_.narrow.glif new file mode 100644 index 00000000..d5643b85 --- /dev/null +++ b/fixtures/fonts/mutatorsans-variable/MutatorSansBoldCondensed.ufo/glyphs/I_.narrow.glif @@ -0,0 +1,24 @@ + + + + + + + + + + + + + + com.typemytype.robofont.Image.Brightness + 0 + com.typemytype.robofont.Image.Contrast + 1 + com.typemytype.robofont.Image.Saturation + 1 + com.typemytype.robofont.Image.Sharpness + 0.4 + + + diff --git a/fixtures/fonts/mutatorsans-variable/MutatorSansBoldCondensed.ufo/glyphs/I_J_.glif b/fixtures/fonts/mutatorsans-variable/MutatorSansBoldCondensed.ufo/glyphs/I_J_.glif new file mode 100644 index 00000000..940e47c9 --- /dev/null +++ b/fixtures/fonts/mutatorsans-variable/MutatorSansBoldCondensed.ufo/glyphs/I_J_.glif @@ -0,0 +1,33 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/fixtures/fonts/mutatorsans-variable/MutatorSansBoldCondensed.ufo/glyphs/J_.glif b/fixtures/fonts/mutatorsans-variable/MutatorSansBoldCondensed.ufo/glyphs/J_.glif new file mode 100644 index 00000000..c4314c24 --- /dev/null +++ b/fixtures/fonts/mutatorsans-variable/MutatorSansBoldCondensed.ufo/glyphs/J_.glif @@ -0,0 +1,27 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/fixtures/fonts/mutatorsans-variable/MutatorSansBoldCondensed.ufo/glyphs/J_.narrow.glif b/fixtures/fonts/mutatorsans-variable/MutatorSansBoldCondensed.ufo/glyphs/J_.narrow.glif new file mode 100644 index 00000000..7a338337 --- /dev/null +++ b/fixtures/fonts/mutatorsans-variable/MutatorSansBoldCondensed.ufo/glyphs/J_.narrow.glif @@ -0,0 +1,24 @@ + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/fixtures/fonts/mutatorsans-variable/MutatorSansBoldCondensed.ufo/glyphs/K_.glif b/fixtures/fonts/mutatorsans-variable/MutatorSansBoldCondensed.ufo/glyphs/K_.glif new file mode 100644 index 00000000..6ab9e08e --- /dev/null +++ b/fixtures/fonts/mutatorsans-variable/MutatorSansBoldCondensed.ufo/glyphs/K_.glif @@ -0,0 +1,28 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/fixtures/fonts/mutatorsans-variable/MutatorSansBoldCondensed.ufo/glyphs/L_.glif b/fixtures/fonts/mutatorsans-variable/MutatorSansBoldCondensed.ufo/glyphs/L_.glif new file mode 100644 index 00000000..a42f84a9 --- /dev/null +++ b/fixtures/fonts/mutatorsans-variable/MutatorSansBoldCondensed.ufo/glyphs/L_.glif @@ -0,0 +1,19 @@ + + + + + + + + + + + + + + + + + + + diff --git a/fixtures/fonts/mutatorsans-variable/MutatorSansBoldCondensed.ufo/glyphs/M_.glif b/fixtures/fonts/mutatorsans-variable/MutatorSansBoldCondensed.ufo/glyphs/M_.glif new file mode 100644 index 00000000..fb238308 --- /dev/null +++ b/fixtures/fonts/mutatorsans-variable/MutatorSansBoldCondensed.ufo/glyphs/M_.glif @@ -0,0 +1,29 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/fixtures/fonts/mutatorsans-variable/MutatorSansBoldCondensed.ufo/glyphs/N_.glif b/fixtures/fonts/mutatorsans-variable/MutatorSansBoldCondensed.ufo/glyphs/N_.glif new file mode 100644 index 00000000..cb50a6d5 --- /dev/null +++ b/fixtures/fonts/mutatorsans-variable/MutatorSansBoldCondensed.ufo/glyphs/N_.glif @@ -0,0 +1,25 @@ + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/fixtures/fonts/mutatorsans-variable/MutatorSansBoldCondensed.ufo/glyphs/O_.glif b/fixtures/fonts/mutatorsans-variable/MutatorSansBoldCondensed.ufo/glyphs/O_.glif new file mode 100644 index 00000000..27def6a1 --- /dev/null +++ b/fixtures/fonts/mutatorsans-variable/MutatorSansBoldCondensed.ufo/glyphs/O_.glif @@ -0,0 +1,39 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/fixtures/fonts/mutatorsans-variable/MutatorSansBoldCondensed.ufo/glyphs/P_.glif b/fixtures/fonts/mutatorsans-variable/MutatorSansBoldCondensed.ufo/glyphs/P_.glif new file mode 100644 index 00000000..66ed04c7 --- /dev/null +++ b/fixtures/fonts/mutatorsans-variable/MutatorSansBoldCondensed.ufo/glyphs/P_.glif @@ -0,0 +1,33 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/fixtures/fonts/mutatorsans-variable/MutatorSansBoldCondensed.ufo/glyphs/Q_.glif b/fixtures/fonts/mutatorsans-variable/MutatorSansBoldCondensed.ufo/glyphs/Q_.glif new file mode 100644 index 00000000..dd1417eb --- /dev/null +++ b/fixtures/fonts/mutatorsans-variable/MutatorSansBoldCondensed.ufo/glyphs/Q_.glif @@ -0,0 +1,14 @@ + + + + + + + + + + + + + + diff --git a/fixtures/fonts/mutatorsans-variable/MutatorSansBoldCondensed.ufo/glyphs/R_.glif b/fixtures/fonts/mutatorsans-variable/MutatorSansBoldCondensed.ufo/glyphs/R_.glif new file mode 100644 index 00000000..952b71e0 --- /dev/null +++ b/fixtures/fonts/mutatorsans-variable/MutatorSansBoldCondensed.ufo/glyphs/R_.glif @@ -0,0 +1,54 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + com.typemytype.robofont.Image.Brightness + 0 + com.typemytype.robofont.Image.Contrast + 1 + com.typemytype.robofont.Image.Saturation + 1 + com.typemytype.robofont.Image.Sharpness + 0.4 + + + diff --git a/fixtures/fonts/mutatorsans-variable/MutatorSansBoldCondensed.ufo/glyphs/S_.closed.glif b/fixtures/fonts/mutatorsans-variable/MutatorSansBoldCondensed.ufo/glyphs/S_.closed.glif new file mode 100644 index 00000000..d5e09976 --- /dev/null +++ b/fixtures/fonts/mutatorsans-variable/MutatorSansBoldCondensed.ufo/glyphs/S_.closed.glif @@ -0,0 +1,66 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + com.letterror.skateboard.navigator + + location + + weight + 1000.0 + width + 108.00694056919657 + + + + + diff --git a/fixtures/fonts/mutatorsans-variable/MutatorSansBoldCondensed.ufo/glyphs/S_.glif b/fixtures/fonts/mutatorsans-variable/MutatorSansBoldCondensed.ufo/glyphs/S_.glif new file mode 100644 index 00000000..a13b97f0 --- /dev/null +++ b/fixtures/fonts/mutatorsans-variable/MutatorSansBoldCondensed.ufo/glyphs/S_.glif @@ -0,0 +1,65 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + com.typemytype.robofont.Image.Brightness + 0 + com.typemytype.robofont.Image.Contrast + 1 + com.typemytype.robofont.Image.Saturation + 1 + com.typemytype.robofont.Image.Sharpness + 0.4 + + + diff --git a/fixtures/fonts/mutatorsans-variable/MutatorSansBoldCondensed.ufo/glyphs/T_.glif b/fixtures/fonts/mutatorsans-variable/MutatorSansBoldCondensed.ufo/glyphs/T_.glif new file mode 100644 index 00000000..3d3e2c8f --- /dev/null +++ b/fixtures/fonts/mutatorsans-variable/MutatorSansBoldCondensed.ufo/glyphs/T_.glif @@ -0,0 +1,19 @@ + + + + + + + + + + + + + + + + + + + diff --git a/fixtures/fonts/mutatorsans-variable/MutatorSansBoldCondensed.ufo/glyphs/U_.glif b/fixtures/fonts/mutatorsans-variable/MutatorSansBoldCondensed.ufo/glyphs/U_.glif new file mode 100644 index 00000000..6752b492 --- /dev/null +++ b/fixtures/fonts/mutatorsans-variable/MutatorSansBoldCondensed.ufo/glyphs/U_.glif @@ -0,0 +1,27 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/fixtures/fonts/mutatorsans-variable/MutatorSansBoldCondensed.ufo/glyphs/V_.glif b/fixtures/fonts/mutatorsans-variable/MutatorSansBoldCondensed.ufo/glyphs/V_.glif new file mode 100644 index 00000000..01087515 --- /dev/null +++ b/fixtures/fonts/mutatorsans-variable/MutatorSansBoldCondensed.ufo/glyphs/V_.glif @@ -0,0 +1,25 @@ + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/fixtures/fonts/mutatorsans-variable/MutatorSansBoldCondensed.ufo/glyphs/W_.glif b/fixtures/fonts/mutatorsans-variable/MutatorSansBoldCondensed.ufo/glyphs/W_.glif new file mode 100644 index 00000000..77d4b763 --- /dev/null +++ b/fixtures/fonts/mutatorsans-variable/MutatorSansBoldCondensed.ufo/glyphs/W_.glif @@ -0,0 +1,25 @@ + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/fixtures/fonts/mutatorsans-variable/MutatorSansBoldCondensed.ufo/glyphs/X_.glif b/fixtures/fonts/mutatorsans-variable/MutatorSansBoldCondensed.ufo/glyphs/X_.glif new file mode 100644 index 00000000..ab7b8723 --- /dev/null +++ b/fixtures/fonts/mutatorsans-variable/MutatorSansBoldCondensed.ufo/glyphs/X_.glif @@ -0,0 +1,25 @@ + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/fixtures/fonts/mutatorsans-variable/MutatorSansBoldCondensed.ufo/glyphs/Y_.glif b/fixtures/fonts/mutatorsans-variable/MutatorSansBoldCondensed.ufo/glyphs/Y_.glif new file mode 100644 index 00000000..1a549a79 --- /dev/null +++ b/fixtures/fonts/mutatorsans-variable/MutatorSansBoldCondensed.ufo/glyphs/Y_.glif @@ -0,0 +1,25 @@ + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/fixtures/fonts/mutatorsans-variable/MutatorSansBoldCondensed.ufo/glyphs/Z_.glif b/fixtures/fonts/mutatorsans-variable/MutatorSansBoldCondensed.ufo/glyphs/Z_.glif new file mode 100644 index 00000000..7e544c78 --- /dev/null +++ b/fixtures/fonts/mutatorsans-variable/MutatorSansBoldCondensed.ufo/glyphs/Z_.glif @@ -0,0 +1,25 @@ + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/fixtures/fonts/mutatorsans-variable/MutatorSansBoldCondensed.ufo/glyphs/_notdef.glif b/fixtures/fonts/mutatorsans-variable/MutatorSansBoldCondensed.ufo/glyphs/_notdef.glif new file mode 100644 index 00000000..7bd7a779 --- /dev/null +++ b/fixtures/fonts/mutatorsans-variable/MutatorSansBoldCondensed.ufo/glyphs/_notdef.glif @@ -0,0 +1,42 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + public.markColor + 0.6567,0.6903,1,1 + + + diff --git a/fixtures/fonts/mutatorsans-variable/MutatorSansBoldCondensed.ufo/glyphs/acute.glif b/fixtures/fonts/mutatorsans-variable/MutatorSansBoldCondensed.ufo/glyphs/acute.glif new file mode 100644 index 00000000..ce8be622 --- /dev/null +++ b/fixtures/fonts/mutatorsans-variable/MutatorSansBoldCondensed.ufo/glyphs/acute.glif @@ -0,0 +1,13 @@ + + + + + + + + + + + + + diff --git a/fixtures/fonts/mutatorsans-variable/MutatorSansBoldCondensed.ufo/glyphs/arrowdown.glif b/fixtures/fonts/mutatorsans-variable/MutatorSansBoldCondensed.ufo/glyphs/arrowdown.glif new file mode 100644 index 00000000..015ae983 --- /dev/null +++ b/fixtures/fonts/mutatorsans-variable/MutatorSansBoldCondensed.ufo/glyphs/arrowdown.glif @@ -0,0 +1,17 @@ + + + + + + + + + + + + + + + + + diff --git a/fixtures/fonts/mutatorsans-variable/MutatorSansBoldCondensed.ufo/glyphs/arrowleft.glif b/fixtures/fonts/mutatorsans-variable/MutatorSansBoldCondensed.ufo/glyphs/arrowleft.glif new file mode 100644 index 00000000..9e425897 --- /dev/null +++ b/fixtures/fonts/mutatorsans-variable/MutatorSansBoldCondensed.ufo/glyphs/arrowleft.glif @@ -0,0 +1,17 @@ + + + + + + + + + + + + + + + + + diff --git a/fixtures/fonts/mutatorsans-variable/MutatorSansBoldCondensed.ufo/glyphs/arrowright.glif b/fixtures/fonts/mutatorsans-variable/MutatorSansBoldCondensed.ufo/glyphs/arrowright.glif new file mode 100644 index 00000000..2211aee8 --- /dev/null +++ b/fixtures/fonts/mutatorsans-variable/MutatorSansBoldCondensed.ufo/glyphs/arrowright.glif @@ -0,0 +1,17 @@ + + + + + + + + + + + + + + + + + diff --git a/fixtures/fonts/mutatorsans-variable/MutatorSansBoldCondensed.ufo/glyphs/arrowup.glif b/fixtures/fonts/mutatorsans-variable/MutatorSansBoldCondensed.ufo/glyphs/arrowup.glif new file mode 100644 index 00000000..ca8b87bc --- /dev/null +++ b/fixtures/fonts/mutatorsans-variable/MutatorSansBoldCondensed.ufo/glyphs/arrowup.glif @@ -0,0 +1,17 @@ + + + + + + + + + + + + + + + + + diff --git a/fixtures/fonts/mutatorsans-variable/MutatorSansBoldCondensed.ufo/glyphs/b.glif b/fixtures/fonts/mutatorsans-variable/MutatorSansBoldCondensed.ufo/glyphs/b.glif new file mode 100644 index 00000000..16accedd --- /dev/null +++ b/fixtures/fonts/mutatorsans-variable/MutatorSansBoldCondensed.ufo/glyphs/b.glif @@ -0,0 +1,7 @@ + + + + + + + diff --git a/fixtures/fonts/mutatorsans-variable/MutatorSansBoldCondensed.ufo/glyphs/c.glif b/fixtures/fonts/mutatorsans-variable/MutatorSansBoldCondensed.ufo/glyphs/c.glif new file mode 100644 index 00000000..0b4b3ccf --- /dev/null +++ b/fixtures/fonts/mutatorsans-variable/MutatorSansBoldCondensed.ufo/glyphs/c.glif @@ -0,0 +1,7 @@ + + + + + + + diff --git a/fixtures/fonts/mutatorsans-variable/MutatorSansBoldCondensed.ufo/glyphs/colon.glif b/fixtures/fonts/mutatorsans-variable/MutatorSansBoldCondensed.ufo/glyphs/colon.glif new file mode 100644 index 00000000..8c164fcb --- /dev/null +++ b/fixtures/fonts/mutatorsans-variable/MutatorSansBoldCondensed.ufo/glyphs/colon.glif @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/fixtures/fonts/mutatorsans-variable/MutatorSansBoldCondensed.ufo/glyphs/comma.glif b/fixtures/fonts/mutatorsans-variable/MutatorSansBoldCondensed.ufo/glyphs/comma.glif new file mode 100644 index 00000000..c43e1904 --- /dev/null +++ b/fixtures/fonts/mutatorsans-variable/MutatorSansBoldCondensed.ufo/glyphs/comma.glif @@ -0,0 +1,23 @@ + + + + + + + + + + + + + + + + + + + public.markColor + 0,0.95,0.95,1 + + + diff --git a/fixtures/fonts/mutatorsans-variable/MutatorSansBoldCondensed.ufo/glyphs/contents.plist b/fixtures/fonts/mutatorsans-variable/MutatorSansBoldCondensed.ufo/glyphs/contents.plist new file mode 100644 index 00000000..45273dee --- /dev/null +++ b/fixtures/fonts/mutatorsans-variable/MutatorSansBoldCondensed.ufo/glyphs/contents.plist @@ -0,0 +1,104 @@ + + + + + .notdef + _notdef.glif + A + A_.glif + Aacute + A_acute.glif + Adieresis + A_dieresis.glif + B + B_.glif + C + C_.glif + D + D_.glif + E + E_.glif + F + F_.glif + G + G_.glif + H + H_.glif + I + I_.glif + I.narrow + I_.narrow.glif + IJ + I_J_.glif + J + J_.glif + J.narrow + J_.narrow.glif + K + K_.glif + L + L_.glif + M + M_.glif + N + N_.glif + O + O_.glif + P + P_.glif + Q + Q_.glif + R + R_.glif + S + S_.glif + S.closed + S_.closed.glif + T + T_.glif + U + U_.glif + V + V_.glif + W + W_.glif + X + X_.glif + Y + Y_.glif + Z + Z_.glif + acute + acute.glif + arrowdown + arrowdown.glif + arrowleft + arrowleft.glif + arrowright + arrowright.glif + arrowup + arrowup.glif + colon + colon.glif + comma + comma.glif + dieresis + dieresis.glif + dot + dot.glif + period + period.glif + quotedblbase + quotedblbase.glif + quotedblleft + quotedblleft.glif + quotedblright + quotedblright.glif + quotesinglbase + quotesinglbase.glif + semicolon + semicolon.glif + space + space.glif + + diff --git a/fixtures/fonts/mutatorsans-variable/MutatorSansBoldCondensed.ufo/glyphs/d.glif b/fixtures/fonts/mutatorsans-variable/MutatorSansBoldCondensed.ufo/glyphs/d.glif new file mode 100644 index 00000000..8fc09610 --- /dev/null +++ b/fixtures/fonts/mutatorsans-variable/MutatorSansBoldCondensed.ufo/glyphs/d.glif @@ -0,0 +1,7 @@ + + + + + + + diff --git a/fixtures/fonts/mutatorsans-variable/MutatorSansBoldCondensed.ufo/glyphs/dieresis.glif b/fixtures/fonts/mutatorsans-variable/MutatorSansBoldCondensed.ufo/glyphs/dieresis.glif new file mode 100644 index 00000000..52693962 --- /dev/null +++ b/fixtures/fonts/mutatorsans-variable/MutatorSansBoldCondensed.ufo/glyphs/dieresis.glif @@ -0,0 +1,15 @@ + + + + + + + + + + + public.markColor + 0.6567,0.6903,1,1 + + + diff --git a/fixtures/fonts/mutatorsans-variable/MutatorSansBoldCondensed.ufo/glyphs/dot.glif b/fixtures/fonts/mutatorsans-variable/MutatorSansBoldCondensed.ufo/glyphs/dot.glif new file mode 100644 index 00000000..8db5cc99 --- /dev/null +++ b/fixtures/fonts/mutatorsans-variable/MutatorSansBoldCondensed.ufo/glyphs/dot.glif @@ -0,0 +1,13 @@ + + + + + + + + + + + + + diff --git a/fixtures/fonts/mutatorsans-variable/MutatorSansBoldCondensed.ufo/glyphs/layerinfo.plist b/fixtures/fonts/mutatorsans-variable/MutatorSansBoldCondensed.ufo/glyphs/layerinfo.plist new file mode 100644 index 00000000..aeeb1b2a --- /dev/null +++ b/fixtures/fonts/mutatorsans-variable/MutatorSansBoldCondensed.ufo/glyphs/layerinfo.plist @@ -0,0 +1,13 @@ + + + + + color + 1,0.75,0,0.7 + lib + + com.typemytype.robofont.segmentType + curve + + + diff --git a/fixtures/fonts/mutatorsans-variable/MutatorSansBoldCondensed.ufo/glyphs/period.glif b/fixtures/fonts/mutatorsans-variable/MutatorSansBoldCondensed.ufo/glyphs/period.glif new file mode 100644 index 00000000..0a0c3be1 --- /dev/null +++ b/fixtures/fonts/mutatorsans-variable/MutatorSansBoldCondensed.ufo/glyphs/period.glif @@ -0,0 +1,19 @@ + + + + + + + + + + + + + + + public.markColor + 0,0.95,0.95,1 + + + diff --git a/fixtures/fonts/mutatorsans-variable/MutatorSansBoldCondensed.ufo/glyphs/quotedblbase.glif b/fixtures/fonts/mutatorsans-variable/MutatorSansBoldCondensed.ufo/glyphs/quotedblbase.glif new file mode 100644 index 00000000..d312caeb --- /dev/null +++ b/fixtures/fonts/mutatorsans-variable/MutatorSansBoldCondensed.ufo/glyphs/quotedblbase.glif @@ -0,0 +1,21 @@ + + + + + + + + + + + com.typemytype.robofont.Image.Brightness + 0 + com.typemytype.robofont.Image.Contrast + 1 + com.typemytype.robofont.Image.Saturation + 1 + com.typemytype.robofont.Image.Sharpness + 0.4 + + + diff --git a/fixtures/fonts/mutatorsans-variable/MutatorSansBoldCondensed.ufo/glyphs/quotedblleft.glif b/fixtures/fonts/mutatorsans-variable/MutatorSansBoldCondensed.ufo/glyphs/quotedblleft.glif new file mode 100644 index 00000000..3e2676ee --- /dev/null +++ b/fixtures/fonts/mutatorsans-variable/MutatorSansBoldCondensed.ufo/glyphs/quotedblleft.glif @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/fixtures/fonts/mutatorsans-variable/MutatorSansBoldCondensed.ufo/glyphs/quotedblright.glif b/fixtures/fonts/mutatorsans-variable/MutatorSansBoldCondensed.ufo/glyphs/quotedblright.glif new file mode 100644 index 00000000..a65d160b --- /dev/null +++ b/fixtures/fonts/mutatorsans-variable/MutatorSansBoldCondensed.ufo/glyphs/quotedblright.glif @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/fixtures/fonts/mutatorsans-variable/MutatorSansBoldCondensed.ufo/glyphs/quotesinglbase.glif b/fixtures/fonts/mutatorsans-variable/MutatorSansBoldCondensed.ufo/glyphs/quotesinglbase.glif new file mode 100644 index 00000000..93c283a3 --- /dev/null +++ b/fixtures/fonts/mutatorsans-variable/MutatorSansBoldCondensed.ufo/glyphs/quotesinglbase.glif @@ -0,0 +1,20 @@ + + + + + + + + + + com.typemytype.robofont.Image.Brightness + 0 + com.typemytype.robofont.Image.Contrast + 1 + com.typemytype.robofont.Image.Saturation + 1 + com.typemytype.robofont.Image.Sharpness + 0.4 + + + diff --git a/fixtures/fonts/mutatorsans-variable/MutatorSansBoldCondensed.ufo/glyphs/semicolon.glif b/fixtures/fonts/mutatorsans-variable/MutatorSansBoldCondensed.ufo/glyphs/semicolon.glif new file mode 100644 index 00000000..c912a8d1 --- /dev/null +++ b/fixtures/fonts/mutatorsans-variable/MutatorSansBoldCondensed.ufo/glyphs/semicolon.glif @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/fixtures/fonts/mutatorsans-variable/MutatorSansBoldCondensed.ufo/glyphs/space.glif b/fixtures/fonts/mutatorsans-variable/MutatorSansBoldCondensed.ufo/glyphs/space.glif new file mode 100644 index 00000000..80c661f7 --- /dev/null +++ b/fixtures/fonts/mutatorsans-variable/MutatorSansBoldCondensed.ufo/glyphs/space.glif @@ -0,0 +1,7 @@ + + + + + + + diff --git a/fixtures/fonts/mutatorsans-variable/MutatorSansBoldCondensed.ufo/groups.plist b/fixtures/fonts/mutatorsans-variable/MutatorSansBoldCondensed.ufo/groups.plist new file mode 100644 index 00000000..7dc9fccd --- /dev/null +++ b/fixtures/fonts/mutatorsans-variable/MutatorSansBoldCondensed.ufo/groups.plist @@ -0,0 +1,20 @@ + + + + + public.kern1.@MMK_L_A + + A + + public.kern2.@MMK_R_A + + A + + testGroup + + E + F + H + + + diff --git a/fixtures/fonts/mutatorsans-variable/MutatorSansBoldCondensed.ufo/kerning.plist b/fixtures/fonts/mutatorsans-variable/MutatorSansBoldCondensed.ufo/kerning.plist new file mode 100644 index 00000000..f5fa18fa --- /dev/null +++ b/fixtures/fonts/mutatorsans-variable/MutatorSansBoldCondensed.ufo/kerning.plist @@ -0,0 +1,210 @@ + + + + + A + + J + -20 + O + -30 + T + -70 + U + -30 + V + -50 + + B + + A + -20 + J + -50 + O + -20 + S + -10 + T + -10 + U + -20 + V + -30 + + C + + A + -20 + J + -50 + T + -20 + V + -20 + + E + + J + -20 + T + -10 + V + -10 + + F + + A + -40 + J + -80 + O + -10 + S + -20 + U + -10 + V + -10 + + G + + J + -20 + S + -10 + T + -40 + U + -10 + V + -30 + + H + + J + -30 + S + -10 + T + -10 + + J + + J + -70 + + L + + J + -20 + O + -20 + T + -110 + U + -20 + V + -60 + + O + + A + -30 + J + -60 + S + -10 + T + -30 + V + -30 + + P + + A + -50 + J + -100 + S + -10 + T + -10 + U + -10 + V + -20 + + R + + H + -10 + J + -20 + O + -30 + S + -20 + T + -30 + U + -30 + V + -40 + + S + + A + -20 + H + -20 + J + -40 + O + -10 + S + -10 + T + -30 + U + -10 + V + -30 + W + -10 + + T + + A + -65 + H + -10 + J + -130 + O + -20 + + U + + A + -30 + J + -60 + S + -10 + V + -10 + + V + + J + -100 + O + -30 + S + -20 + U + -10 + + + diff --git a/fixtures/fonts/mutatorsans-variable/MutatorSansBoldCondensed.ufo/layercontents.plist b/fixtures/fonts/mutatorsans-variable/MutatorSansBoldCondensed.ufo/layercontents.plist new file mode 100644 index 00000000..e9a336b2 --- /dev/null +++ b/fixtures/fonts/mutatorsans-variable/MutatorSansBoldCondensed.ufo/layercontents.plist @@ -0,0 +1,14 @@ + + + + + + foreground + glyphs + + + background + glyphs.background + + + diff --git a/fixtures/fonts/mutatorsans-variable/MutatorSansBoldCondensed.ufo/lib.plist b/fixtures/fonts/mutatorsans-variable/MutatorSansBoldCondensed.ufo/lib.plist new file mode 100644 index 00000000..f3fa5b5f --- /dev/null +++ b/fixtures/fonts/mutatorsans-variable/MutatorSansBoldCondensed.ufo/lib.plist @@ -0,0 +1,229 @@ + + + + + com.defcon.sortDescriptor + + + allowPseudoUnicode + + type + cannedDesign + + + com.letterror.lightMeter.prefs + + chunkSize + 5 + diameter + 200 + drawTail + + invert + + toolDiameter + 30 + toolStyle + fluid + + com.typemytype.robofont.background.layerStrokeColor + + 0.0 + 0.8 + 0.2 + 0.7 + + com.typemytype.robofont.compileSettings.autohint + + com.typemytype.robofont.compileSettings.checkOutlines + + com.typemytype.robofont.compileSettings.createDummyDSIG + + com.typemytype.robofont.compileSettings.decompose + + com.typemytype.robofont.compileSettings.generateFormat + 0 + com.typemytype.robofont.compileSettings.releaseMode + + com.typemytype.robofont.foreground.layerStrokeColor + + 0.5 + 0.0 + 0.5 + 0.7 + + com.typemytype.robofont.italicSlantOffset + 0 + com.typemytype.robofont.segmentType + curve + com.typemytype.robofont.shouldAddPointsInSplineConversion + 1 + com.typesupply.defcon.sortDescriptor + + + ascending + + space + A + B + C + D + E + F + G + H + I + J + K + L + M + N + O + P + Q + R + S + T + U + V + W + X + Y + Z + a + b + c + d + e + f + g + h + i + j + k + l + m + n + ntilde + o + p + q + r + s + t + u + v + w + x + y + z + zcaron + zero + one + two + three + four + five + six + seven + eight + nine + underscore + hyphen + endash + emdash + parenleft + parenright + bracketleft + bracketright + braceleft + braceright + numbersign + percent + period + comma + colon + semicolon + exclam + question + slash + backslash + bar + at + ampersand + paragraph + bullet + dollar + trademark + fi + fl + .notdef + a_b_c + Atilde + Adieresis + Acircumflex + Aring + Ccedilla + Agrave + Aacute + quotedblright + quotedblleft + + type + glyphList + + + public.glyphOrder + + space + A + Aacute + Adieresis + B + C + D + E + F + G + H + I + J + K + L + M + N + O + P + Q + R + S + T + U + V + W + X + Y + Z + IJ + quotedblleft + quotedblright + quotesinglbase + quotedblbase + period + comma + colon + semicolon + dot + acute + dieresis + arrowdown + arrowleft + arrowright + arrowup + I.narrow + J.narrow + S.closed + .notdef + + + diff --git a/fixtures/fonts/mutatorsans-variable/MutatorSansBoldCondensed.ufo/metainfo.plist b/fixtures/fonts/mutatorsans-variable/MutatorSansBoldCondensed.ufo/metainfo.plist new file mode 100644 index 00000000..7b8b34ac --- /dev/null +++ b/fixtures/fonts/mutatorsans-variable/MutatorSansBoldCondensed.ufo/metainfo.plist @@ -0,0 +1,10 @@ + + + + + creator + com.github.fonttools.ufoLib + formatVersion + 3 + + diff --git a/fixtures/fonts/mutatorsans-variable/MutatorSansBoldWide.ufo/features.fea b/fixtures/fonts/mutatorsans-variable/MutatorSansBoldWide.ufo/features.fea new file mode 100644 index 00000000..70ab5da3 --- /dev/null +++ b/fixtures/fonts/mutatorsans-variable/MutatorSansBoldWide.ufo/features.fea @@ -0,0 +1,3 @@ +# this is the feature from BoldWide +languagesystem DFLT dflt; +languagesystem latn dflt; diff --git a/fixtures/fonts/mutatorsans-variable/MutatorSansBoldWide.ufo/fontinfo.plist b/fixtures/fonts/mutatorsans-variable/MutatorSansBoldWide.ufo/fontinfo.plist new file mode 100644 index 00000000..760fc3da --- /dev/null +++ b/fixtures/fonts/mutatorsans-variable/MutatorSansBoldWide.ufo/fontinfo.plist @@ -0,0 +1,68 @@ + + + + + ascender + 800 + capHeight + 800 + copyright + License same as MutatorMath. BSD 3-clause. [test-token: B] + descender + -200 + familyName + MutatorSans + guidelines + + italicAngle + 0 + openTypeNameLicense + License same as MutatorMath. BSD 3-clause. [test-token: B] + openTypeOS2VendorID + LTTR + postscriptBlueValues + + -10 + 0 + 800 + 810 + + postscriptDefaultWidthX + 500 + postscriptFamilyBlues + + postscriptFamilyOtherBlues + + postscriptFontName + MutatorSans-BoldWide + postscriptOtherBlues + + 400 + 420 + + postscriptSlantAngle + 0 + postscriptStemSnapH + + postscriptStemSnapV + + postscriptWindowsCharacterSet + 1 + styleMapFamilyName + + styleMapStyleName + regular + styleName + BoldWide + unitsPerEm + 1000 + versionMajor + 1 + versionMinor + 2 + xHeight + 500 + year + 2004 + + diff --git a/fixtures/fonts/mutatorsans-variable/MutatorSansBoldWide.ufo/glyphs.background/S_.closed.glif b/fixtures/fonts/mutatorsans-variable/MutatorSansBoldWide.ufo/glyphs.background/S_.closed.glif new file mode 100644 index 00000000..71c82094 --- /dev/null +++ b/fixtures/fonts/mutatorsans-variable/MutatorSansBoldWide.ufo/glyphs.background/S_.closed.glif @@ -0,0 +1,52 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/fixtures/fonts/mutatorsans-variable/MutatorSansBoldWide.ufo/glyphs.background/S_.glif b/fixtures/fonts/mutatorsans-variable/MutatorSansBoldWide.ufo/glyphs.background/S_.glif new file mode 100644 index 00000000..5e0ed4d8 --- /dev/null +++ b/fixtures/fonts/mutatorsans-variable/MutatorSansBoldWide.ufo/glyphs.background/S_.glif @@ -0,0 +1,53 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/fixtures/fonts/mutatorsans-variable/MutatorSansBoldWide.ufo/glyphs.background/contents.plist b/fixtures/fonts/mutatorsans-variable/MutatorSansBoldWide.ufo/glyphs.background/contents.plist new file mode 100644 index 00000000..701b513a --- /dev/null +++ b/fixtures/fonts/mutatorsans-variable/MutatorSansBoldWide.ufo/glyphs.background/contents.plist @@ -0,0 +1,10 @@ + + + + + S + S_.glif + S.closed + S_.closed.glif + + diff --git a/fixtures/fonts/mutatorsans-variable/MutatorSansBoldWide.ufo/glyphs.background/layerinfo.plist b/fixtures/fonts/mutatorsans-variable/MutatorSansBoldWide.ufo/glyphs.background/layerinfo.plist new file mode 100644 index 00000000..7e385c7f --- /dev/null +++ b/fixtures/fonts/mutatorsans-variable/MutatorSansBoldWide.ufo/glyphs.background/layerinfo.plist @@ -0,0 +1,8 @@ + + + + + color + 0.5,1,0,0.7 + + diff --git a/fixtures/fonts/mutatorsans-variable/MutatorSansBoldWide.ufo/glyphs.crayon/S_.glif b/fixtures/fonts/mutatorsans-variable/MutatorSansBoldWide.ufo/glyphs.crayon/S_.glif new file mode 100644 index 00000000..3e708495 --- /dev/null +++ b/fixtures/fonts/mutatorsans-variable/MutatorSansBoldWide.ufo/glyphs.crayon/S_.glif @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/fixtures/fonts/mutatorsans-variable/MutatorSansBoldWide.ufo/glyphs.crayon/contents.plist b/fixtures/fonts/mutatorsans-variable/MutatorSansBoldWide.ufo/glyphs.crayon/contents.plist new file mode 100644 index 00000000..41c1aaf9 --- /dev/null +++ b/fixtures/fonts/mutatorsans-variable/MutatorSansBoldWide.ufo/glyphs.crayon/contents.plist @@ -0,0 +1,8 @@ + + + + + S + S_.glif + + diff --git a/fixtures/fonts/mutatorsans-variable/MutatorSansBoldWide.ufo/glyphs.crayon/layerinfo.plist b/fixtures/fonts/mutatorsans-variable/MutatorSansBoldWide.ufo/glyphs.crayon/layerinfo.plist new file mode 100644 index 00000000..321e50a8 --- /dev/null +++ b/fixtures/fonts/mutatorsans-variable/MutatorSansBoldWide.ufo/glyphs.crayon/layerinfo.plist @@ -0,0 +1,8 @@ + + + + + color + 0,1,0.25,0.7 + + diff --git a/fixtures/fonts/mutatorsans-variable/MutatorSansBoldWide.ufo/glyphs/A_.glif b/fixtures/fonts/mutatorsans-variable/MutatorSansBoldWide.ufo/glyphs/A_.glif new file mode 100644 index 00000000..58f75c00 --- /dev/null +++ b/fixtures/fonts/mutatorsans-variable/MutatorSansBoldWide.ufo/glyphs/A_.glif @@ -0,0 +1,31 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/fixtures/fonts/mutatorsans-variable/MutatorSansBoldWide.ufo/glyphs/A_acute.glif b/fixtures/fonts/mutatorsans-variable/MutatorSansBoldWide.ufo/glyphs/A_acute.glif new file mode 100644 index 00000000..d220f280 --- /dev/null +++ b/fixtures/fonts/mutatorsans-variable/MutatorSansBoldWide.ufo/glyphs/A_acute.glif @@ -0,0 +1,15 @@ + + + + + + + + + + + public.markColor + 0.6567,0.6903,1,1 + + + diff --git a/fixtures/fonts/mutatorsans-variable/MutatorSansBoldWide.ufo/glyphs/A_dieresis.glif b/fixtures/fonts/mutatorsans-variable/MutatorSansBoldWide.ufo/glyphs/A_dieresis.glif new file mode 100644 index 00000000..7862d2f1 --- /dev/null +++ b/fixtures/fonts/mutatorsans-variable/MutatorSansBoldWide.ufo/glyphs/A_dieresis.glif @@ -0,0 +1,15 @@ + + + + + + + + + + + public.markColor + 0.6567,0.6903,1,1 + + + diff --git a/fixtures/fonts/mutatorsans-variable/MutatorSansBoldWide.ufo/glyphs/B_.glif b/fixtures/fonts/mutatorsans-variable/MutatorSansBoldWide.ufo/glyphs/B_.glif new file mode 100644 index 00000000..70bc5a7c --- /dev/null +++ b/fixtures/fonts/mutatorsans-variable/MutatorSansBoldWide.ufo/glyphs/B_.glif @@ -0,0 +1,61 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + com.typemytype.robofont.Image.Brightness + 0 + com.typemytype.robofont.Image.Contrast + 1 + com.typemytype.robofont.Image.Saturation + 1 + com.typemytype.robofont.Image.Sharpness + 0.4 + + + diff --git a/fixtures/fonts/mutatorsans-variable/MutatorSansBoldWide.ufo/glyphs/C_.glif b/fixtures/fonts/mutatorsans-variable/MutatorSansBoldWide.ufo/glyphs/C_.glif new file mode 100644 index 00000000..92eea0f1 --- /dev/null +++ b/fixtures/fonts/mutatorsans-variable/MutatorSansBoldWide.ufo/glyphs/C_.glif @@ -0,0 +1,39 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/fixtures/fonts/mutatorsans-variable/MutatorSansBoldWide.ufo/glyphs/D_.glif b/fixtures/fonts/mutatorsans-variable/MutatorSansBoldWide.ufo/glyphs/D_.glif new file mode 100644 index 00000000..5a50cb1a --- /dev/null +++ b/fixtures/fonts/mutatorsans-variable/MutatorSansBoldWide.ufo/glyphs/D_.glif @@ -0,0 +1,33 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/fixtures/fonts/mutatorsans-variable/MutatorSansBoldWide.ufo/glyphs/E_.glif b/fixtures/fonts/mutatorsans-variable/MutatorSansBoldWide.ufo/glyphs/E_.glif new file mode 100644 index 00000000..1330903b --- /dev/null +++ b/fixtures/fonts/mutatorsans-variable/MutatorSansBoldWide.ufo/glyphs/E_.glif @@ -0,0 +1,32 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/fixtures/fonts/mutatorsans-variable/MutatorSansBoldWide.ufo/glyphs/F_.glif b/fixtures/fonts/mutatorsans-variable/MutatorSansBoldWide.ufo/glyphs/F_.glif new file mode 100644 index 00000000..c62c5a01 --- /dev/null +++ b/fixtures/fonts/mutatorsans-variable/MutatorSansBoldWide.ufo/glyphs/F_.glif @@ -0,0 +1,25 @@ + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/fixtures/fonts/mutatorsans-variable/MutatorSansBoldWide.ufo/glyphs/G_.glif b/fixtures/fonts/mutatorsans-variable/MutatorSansBoldWide.ufo/glyphs/G_.glif new file mode 100644 index 00000000..5f1b1813 --- /dev/null +++ b/fixtures/fonts/mutatorsans-variable/MutatorSansBoldWide.ufo/glyphs/G_.glif @@ -0,0 +1,48 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/fixtures/fonts/mutatorsans-variable/MutatorSansBoldWide.ufo/glyphs/H_.glif b/fixtures/fonts/mutatorsans-variable/MutatorSansBoldWide.ufo/glyphs/H_.glif new file mode 100644 index 00000000..f0a95e47 --- /dev/null +++ b/fixtures/fonts/mutatorsans-variable/MutatorSansBoldWide.ufo/glyphs/H_.glif @@ -0,0 +1,25 @@ + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/fixtures/fonts/mutatorsans-variable/MutatorSansBoldWide.ufo/glyphs/I_.glif b/fixtures/fonts/mutatorsans-variable/MutatorSansBoldWide.ufo/glyphs/I_.glif new file mode 100644 index 00000000..a013c998 --- /dev/null +++ b/fixtures/fonts/mutatorsans-variable/MutatorSansBoldWide.ufo/glyphs/I_.glif @@ -0,0 +1,25 @@ + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/fixtures/fonts/mutatorsans-variable/MutatorSansBoldWide.ufo/glyphs/I_.narrow.glif b/fixtures/fonts/mutatorsans-variable/MutatorSansBoldWide.ufo/glyphs/I_.narrow.glif new file mode 100644 index 00000000..111c8b61 --- /dev/null +++ b/fixtures/fonts/mutatorsans-variable/MutatorSansBoldWide.ufo/glyphs/I_.narrow.glif @@ -0,0 +1,24 @@ + + + + + + + + + + + + + + com.typemytype.robofont.Image.Brightness + 0 + com.typemytype.robofont.Image.Contrast + 1 + com.typemytype.robofont.Image.Saturation + 1 + com.typemytype.robofont.Image.Sharpness + 0.4 + + + diff --git a/fixtures/fonts/mutatorsans-variable/MutatorSansBoldWide.ufo/glyphs/I_J_.glif b/fixtures/fonts/mutatorsans-variable/MutatorSansBoldWide.ufo/glyphs/I_J_.glif new file mode 100644 index 00000000..072b87d8 --- /dev/null +++ b/fixtures/fonts/mutatorsans-variable/MutatorSansBoldWide.ufo/glyphs/I_J_.glif @@ -0,0 +1,32 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/fixtures/fonts/mutatorsans-variable/MutatorSansBoldWide.ufo/glyphs/J_.glif b/fixtures/fonts/mutatorsans-variable/MutatorSansBoldWide.ufo/glyphs/J_.glif new file mode 100644 index 00000000..1e41faac --- /dev/null +++ b/fixtures/fonts/mutatorsans-variable/MutatorSansBoldWide.ufo/glyphs/J_.glif @@ -0,0 +1,27 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/fixtures/fonts/mutatorsans-variable/MutatorSansBoldWide.ufo/glyphs/J_.narrow.glif b/fixtures/fonts/mutatorsans-variable/MutatorSansBoldWide.ufo/glyphs/J_.narrow.glif new file mode 100644 index 00000000..393a0310 --- /dev/null +++ b/fixtures/fonts/mutatorsans-variable/MutatorSansBoldWide.ufo/glyphs/J_.narrow.glif @@ -0,0 +1,24 @@ + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/fixtures/fonts/mutatorsans-variable/MutatorSansBoldWide.ufo/glyphs/K_.glif b/fixtures/fonts/mutatorsans-variable/MutatorSansBoldWide.ufo/glyphs/K_.glif new file mode 100644 index 00000000..73f5683c --- /dev/null +++ b/fixtures/fonts/mutatorsans-variable/MutatorSansBoldWide.ufo/glyphs/K_.glif @@ -0,0 +1,28 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/fixtures/fonts/mutatorsans-variable/MutatorSansBoldWide.ufo/glyphs/L_.glif b/fixtures/fonts/mutatorsans-variable/MutatorSansBoldWide.ufo/glyphs/L_.glif new file mode 100644 index 00000000..bc9a4d94 --- /dev/null +++ b/fixtures/fonts/mutatorsans-variable/MutatorSansBoldWide.ufo/glyphs/L_.glif @@ -0,0 +1,19 @@ + + + + + + + + + + + + + + + + + + + diff --git a/fixtures/fonts/mutatorsans-variable/MutatorSansBoldWide.ufo/glyphs/M_.glif b/fixtures/fonts/mutatorsans-variable/MutatorSansBoldWide.ufo/glyphs/M_.glif new file mode 100644 index 00000000..c16bdd6a --- /dev/null +++ b/fixtures/fonts/mutatorsans-variable/MutatorSansBoldWide.ufo/glyphs/M_.glif @@ -0,0 +1,29 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/fixtures/fonts/mutatorsans-variable/MutatorSansBoldWide.ufo/glyphs/N_.glif b/fixtures/fonts/mutatorsans-variable/MutatorSansBoldWide.ufo/glyphs/N_.glif new file mode 100644 index 00000000..ab808746 --- /dev/null +++ b/fixtures/fonts/mutatorsans-variable/MutatorSansBoldWide.ufo/glyphs/N_.glif @@ -0,0 +1,25 @@ + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/fixtures/fonts/mutatorsans-variable/MutatorSansBoldWide.ufo/glyphs/O_.glif b/fixtures/fonts/mutatorsans-variable/MutatorSansBoldWide.ufo/glyphs/O_.glif new file mode 100644 index 00000000..acd36a1b --- /dev/null +++ b/fixtures/fonts/mutatorsans-variable/MutatorSansBoldWide.ufo/glyphs/O_.glif @@ -0,0 +1,39 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/fixtures/fonts/mutatorsans-variable/MutatorSansBoldWide.ufo/glyphs/P_.glif b/fixtures/fonts/mutatorsans-variable/MutatorSansBoldWide.ufo/glyphs/P_.glif new file mode 100644 index 00000000..1cc7ce1f --- /dev/null +++ b/fixtures/fonts/mutatorsans-variable/MutatorSansBoldWide.ufo/glyphs/P_.glif @@ -0,0 +1,33 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/fixtures/fonts/mutatorsans-variable/MutatorSansBoldWide.ufo/glyphs/Q_.glif b/fixtures/fonts/mutatorsans-variable/MutatorSansBoldWide.ufo/glyphs/Q_.glif new file mode 100644 index 00000000..99f124b3 --- /dev/null +++ b/fixtures/fonts/mutatorsans-variable/MutatorSansBoldWide.ufo/glyphs/Q_.glif @@ -0,0 +1,13 @@ + + + + + + + + + + + + + diff --git a/fixtures/fonts/mutatorsans-variable/MutatorSansBoldWide.ufo/glyphs/R_.glif b/fixtures/fonts/mutatorsans-variable/MutatorSansBoldWide.ufo/glyphs/R_.glif new file mode 100644 index 00000000..74b245b1 --- /dev/null +++ b/fixtures/fonts/mutatorsans-variable/MutatorSansBoldWide.ufo/glyphs/R_.glif @@ -0,0 +1,42 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/fixtures/fonts/mutatorsans-variable/MutatorSansBoldWide.ufo/glyphs/S_.closed.glif b/fixtures/fonts/mutatorsans-variable/MutatorSansBoldWide.ufo/glyphs/S_.closed.glif new file mode 100644 index 00000000..0796d29e --- /dev/null +++ b/fixtures/fonts/mutatorsans-variable/MutatorSansBoldWide.ufo/glyphs/S_.closed.glif @@ -0,0 +1,64 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + com.typemytype.robofont.Image.Brightness + 0 + com.typemytype.robofont.Image.Contrast + 1 + com.typemytype.robofont.Image.Saturation + 1 + com.typemytype.robofont.Image.Sharpness + 0.4 + + + diff --git a/fixtures/fonts/mutatorsans-variable/MutatorSansBoldWide.ufo/glyphs/S_.glif b/fixtures/fonts/mutatorsans-variable/MutatorSansBoldWide.ufo/glyphs/S_.glif new file mode 100644 index 00000000..c64d01f7 --- /dev/null +++ b/fixtures/fonts/mutatorsans-variable/MutatorSansBoldWide.ufo/glyphs/S_.glif @@ -0,0 +1,65 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + com.typemytype.robofont.Image.Brightness + 0 + com.typemytype.robofont.Image.Contrast + 1 + com.typemytype.robofont.Image.Saturation + 1 + com.typemytype.robofont.Image.Sharpness + 0.4 + + + diff --git a/fixtures/fonts/mutatorsans-variable/MutatorSansBoldWide.ufo/glyphs/T_.glif b/fixtures/fonts/mutatorsans-variable/MutatorSansBoldWide.ufo/glyphs/T_.glif new file mode 100644 index 00000000..36a192c8 --- /dev/null +++ b/fixtures/fonts/mutatorsans-variable/MutatorSansBoldWide.ufo/glyphs/T_.glif @@ -0,0 +1,19 @@ + + + + + + + + + + + + + + + + + + + diff --git a/fixtures/fonts/mutatorsans-variable/MutatorSansBoldWide.ufo/glyphs/U_.glif b/fixtures/fonts/mutatorsans-variable/MutatorSansBoldWide.ufo/glyphs/U_.glif new file mode 100644 index 00000000..fcbb5284 --- /dev/null +++ b/fixtures/fonts/mutatorsans-variable/MutatorSansBoldWide.ufo/glyphs/U_.glif @@ -0,0 +1,27 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/fixtures/fonts/mutatorsans-variable/MutatorSansBoldWide.ufo/glyphs/V_.glif b/fixtures/fonts/mutatorsans-variable/MutatorSansBoldWide.ufo/glyphs/V_.glif new file mode 100644 index 00000000..21a3bbef --- /dev/null +++ b/fixtures/fonts/mutatorsans-variable/MutatorSansBoldWide.ufo/glyphs/V_.glif @@ -0,0 +1,25 @@ + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/fixtures/fonts/mutatorsans-variable/MutatorSansBoldWide.ufo/glyphs/W_.glif b/fixtures/fonts/mutatorsans-variable/MutatorSansBoldWide.ufo/glyphs/W_.glif new file mode 100644 index 00000000..6d07876a --- /dev/null +++ b/fixtures/fonts/mutatorsans-variable/MutatorSansBoldWide.ufo/glyphs/W_.glif @@ -0,0 +1,25 @@ + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/fixtures/fonts/mutatorsans-variable/MutatorSansBoldWide.ufo/glyphs/X_.glif b/fixtures/fonts/mutatorsans-variable/MutatorSansBoldWide.ufo/glyphs/X_.glif new file mode 100644 index 00000000..0cdb44c4 --- /dev/null +++ b/fixtures/fonts/mutatorsans-variable/MutatorSansBoldWide.ufo/glyphs/X_.glif @@ -0,0 +1,25 @@ + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/fixtures/fonts/mutatorsans-variable/MutatorSansBoldWide.ufo/glyphs/Y_.glif b/fixtures/fonts/mutatorsans-variable/MutatorSansBoldWide.ufo/glyphs/Y_.glif new file mode 100644 index 00000000..a3175182 --- /dev/null +++ b/fixtures/fonts/mutatorsans-variable/MutatorSansBoldWide.ufo/glyphs/Y_.glif @@ -0,0 +1,25 @@ + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/fixtures/fonts/mutatorsans-variable/MutatorSansBoldWide.ufo/glyphs/Z_.glif b/fixtures/fonts/mutatorsans-variable/MutatorSansBoldWide.ufo/glyphs/Z_.glif new file mode 100644 index 00000000..3b9ef90e --- /dev/null +++ b/fixtures/fonts/mutatorsans-variable/MutatorSansBoldWide.ufo/glyphs/Z_.glif @@ -0,0 +1,25 @@ + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/fixtures/fonts/mutatorsans-variable/MutatorSansBoldWide.ufo/glyphs/_notdef.glif b/fixtures/fonts/mutatorsans-variable/MutatorSansBoldWide.ufo/glyphs/_notdef.glif new file mode 100644 index 00000000..7bd7a779 --- /dev/null +++ b/fixtures/fonts/mutatorsans-variable/MutatorSansBoldWide.ufo/glyphs/_notdef.glif @@ -0,0 +1,42 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + public.markColor + 0.6567,0.6903,1,1 + + + diff --git a/fixtures/fonts/mutatorsans-variable/MutatorSansBoldWide.ufo/glyphs/acute.glif b/fixtures/fonts/mutatorsans-variable/MutatorSansBoldWide.ufo/glyphs/acute.glif new file mode 100644 index 00000000..a61baaec --- /dev/null +++ b/fixtures/fonts/mutatorsans-variable/MutatorSansBoldWide.ufo/glyphs/acute.glif @@ -0,0 +1,13 @@ + + + + + + + + + + + + + diff --git a/fixtures/fonts/mutatorsans-variable/MutatorSansBoldWide.ufo/glyphs/arrowdown.glif b/fixtures/fonts/mutatorsans-variable/MutatorSansBoldWide.ufo/glyphs/arrowdown.glif new file mode 100644 index 00000000..e3c8cd28 --- /dev/null +++ b/fixtures/fonts/mutatorsans-variable/MutatorSansBoldWide.ufo/glyphs/arrowdown.glif @@ -0,0 +1,17 @@ + + + + + + + + + + + + + + + + + diff --git a/fixtures/fonts/mutatorsans-variable/MutatorSansBoldWide.ufo/glyphs/arrowleft.glif b/fixtures/fonts/mutatorsans-variable/MutatorSansBoldWide.ufo/glyphs/arrowleft.glif new file mode 100644 index 00000000..764a5b40 --- /dev/null +++ b/fixtures/fonts/mutatorsans-variable/MutatorSansBoldWide.ufo/glyphs/arrowleft.glif @@ -0,0 +1,17 @@ + + + + + + + + + + + + + + + + + diff --git a/fixtures/fonts/mutatorsans-variable/MutatorSansBoldWide.ufo/glyphs/arrowright.glif b/fixtures/fonts/mutatorsans-variable/MutatorSansBoldWide.ufo/glyphs/arrowright.glif new file mode 100644 index 00000000..e107939b --- /dev/null +++ b/fixtures/fonts/mutatorsans-variable/MutatorSansBoldWide.ufo/glyphs/arrowright.glif @@ -0,0 +1,17 @@ + + + + + + + + + + + + + + + + + diff --git a/fixtures/fonts/mutatorsans-variable/MutatorSansBoldWide.ufo/glyphs/arrowup.glif b/fixtures/fonts/mutatorsans-variable/MutatorSansBoldWide.ufo/glyphs/arrowup.glif new file mode 100644 index 00000000..f5dacf21 --- /dev/null +++ b/fixtures/fonts/mutatorsans-variable/MutatorSansBoldWide.ufo/glyphs/arrowup.glif @@ -0,0 +1,17 @@ + + + + + + + + + + + + + + + + + diff --git a/fixtures/fonts/mutatorsans-variable/MutatorSansBoldWide.ufo/glyphs/colon.glif b/fixtures/fonts/mutatorsans-variable/MutatorSansBoldWide.ufo/glyphs/colon.glif new file mode 100644 index 00000000..91e80845 --- /dev/null +++ b/fixtures/fonts/mutatorsans-variable/MutatorSansBoldWide.ufo/glyphs/colon.glif @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/fixtures/fonts/mutatorsans-variable/MutatorSansBoldWide.ufo/glyphs/comma.glif b/fixtures/fonts/mutatorsans-variable/MutatorSansBoldWide.ufo/glyphs/comma.glif new file mode 100644 index 00000000..b26d079b --- /dev/null +++ b/fixtures/fonts/mutatorsans-variable/MutatorSansBoldWide.ufo/glyphs/comma.glif @@ -0,0 +1,17 @@ + + + + + + + + + + + + + + + + + diff --git a/fixtures/fonts/mutatorsans-variable/MutatorSansBoldWide.ufo/glyphs/contents.plist b/fixtures/fonts/mutatorsans-variable/MutatorSansBoldWide.ufo/glyphs/contents.plist new file mode 100644 index 00000000..45273dee --- /dev/null +++ b/fixtures/fonts/mutatorsans-variable/MutatorSansBoldWide.ufo/glyphs/contents.plist @@ -0,0 +1,104 @@ + + + + + .notdef + _notdef.glif + A + A_.glif + Aacute + A_acute.glif + Adieresis + A_dieresis.glif + B + B_.glif + C + C_.glif + D + D_.glif + E + E_.glif + F + F_.glif + G + G_.glif + H + H_.glif + I + I_.glif + I.narrow + I_.narrow.glif + IJ + I_J_.glif + J + J_.glif + J.narrow + J_.narrow.glif + K + K_.glif + L + L_.glif + M + M_.glif + N + N_.glif + O + O_.glif + P + P_.glif + Q + Q_.glif + R + R_.glif + S + S_.glif + S.closed + S_.closed.glif + T + T_.glif + U + U_.glif + V + V_.glif + W + W_.glif + X + X_.glif + Y + Y_.glif + Z + Z_.glif + acute + acute.glif + arrowdown + arrowdown.glif + arrowleft + arrowleft.glif + arrowright + arrowright.glif + arrowup + arrowup.glif + colon + colon.glif + comma + comma.glif + dieresis + dieresis.glif + dot + dot.glif + period + period.glif + quotedblbase + quotedblbase.glif + quotedblleft + quotedblleft.glif + quotedblright + quotedblright.glif + quotesinglbase + quotesinglbase.glif + semicolon + semicolon.glif + space + space.glif + + diff --git a/fixtures/fonts/mutatorsans-variable/MutatorSansBoldWide.ufo/glyphs/dieresis.glif b/fixtures/fonts/mutatorsans-variable/MutatorSansBoldWide.ufo/glyphs/dieresis.glif new file mode 100644 index 00000000..67e2f61b --- /dev/null +++ b/fixtures/fonts/mutatorsans-variable/MutatorSansBoldWide.ufo/glyphs/dieresis.glif @@ -0,0 +1,15 @@ + + + + + + + + + + + public.markColor + 0.6567,0.6903,1,1 + + + diff --git a/fixtures/fonts/mutatorsans-variable/MutatorSansBoldWide.ufo/glyphs/dot.glif b/fixtures/fonts/mutatorsans-variable/MutatorSansBoldWide.ufo/glyphs/dot.glif new file mode 100644 index 00000000..8db5cc99 --- /dev/null +++ b/fixtures/fonts/mutatorsans-variable/MutatorSansBoldWide.ufo/glyphs/dot.glif @@ -0,0 +1,13 @@ + + + + + + + + + + + + + diff --git a/fixtures/fonts/mutatorsans-variable/MutatorSansBoldWide.ufo/glyphs/layerinfo.plist b/fixtures/fonts/mutatorsans-variable/MutatorSansBoldWide.ufo/glyphs/layerinfo.plist new file mode 100644 index 00000000..aeeb1b2a --- /dev/null +++ b/fixtures/fonts/mutatorsans-variable/MutatorSansBoldWide.ufo/glyphs/layerinfo.plist @@ -0,0 +1,13 @@ + + + + + color + 1,0.75,0,0.7 + lib + + com.typemytype.robofont.segmentType + curve + + + diff --git a/fixtures/fonts/mutatorsans-variable/MutatorSansBoldWide.ufo/glyphs/period.glif b/fixtures/fonts/mutatorsans-variable/MutatorSansBoldWide.ufo/glyphs/period.glif new file mode 100644 index 00000000..e00bdfa1 --- /dev/null +++ b/fixtures/fonts/mutatorsans-variable/MutatorSansBoldWide.ufo/glyphs/period.glif @@ -0,0 +1,13 @@ + + + + + + + + + + + + + diff --git a/fixtures/fonts/mutatorsans-variable/MutatorSansBoldWide.ufo/glyphs/quotedblbase.glif b/fixtures/fonts/mutatorsans-variable/MutatorSansBoldWide.ufo/glyphs/quotedblbase.glif new file mode 100644 index 00000000..cc87c1ce --- /dev/null +++ b/fixtures/fonts/mutatorsans-variable/MutatorSansBoldWide.ufo/glyphs/quotedblbase.glif @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/fixtures/fonts/mutatorsans-variable/MutatorSansBoldWide.ufo/glyphs/quotedblleft.glif b/fixtures/fonts/mutatorsans-variable/MutatorSansBoldWide.ufo/glyphs/quotedblleft.glif new file mode 100644 index 00000000..aee8eba1 --- /dev/null +++ b/fixtures/fonts/mutatorsans-variable/MutatorSansBoldWide.ufo/glyphs/quotedblleft.glif @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/fixtures/fonts/mutatorsans-variable/MutatorSansBoldWide.ufo/glyphs/quotedblright.glif b/fixtures/fonts/mutatorsans-variable/MutatorSansBoldWide.ufo/glyphs/quotedblright.glif new file mode 100644 index 00000000..54e4dbe1 --- /dev/null +++ b/fixtures/fonts/mutatorsans-variable/MutatorSansBoldWide.ufo/glyphs/quotedblright.glif @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/fixtures/fonts/mutatorsans-variable/MutatorSansBoldWide.ufo/glyphs/quotesinglbase.glif b/fixtures/fonts/mutatorsans-variable/MutatorSansBoldWide.ufo/glyphs/quotesinglbase.glif new file mode 100644 index 00000000..65a94da6 --- /dev/null +++ b/fixtures/fonts/mutatorsans-variable/MutatorSansBoldWide.ufo/glyphs/quotesinglbase.glif @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/fixtures/fonts/mutatorsans-variable/MutatorSansBoldWide.ufo/glyphs/semicolon.glif b/fixtures/fonts/mutatorsans-variable/MutatorSansBoldWide.ufo/glyphs/semicolon.glif new file mode 100644 index 00000000..3d21bb11 --- /dev/null +++ b/fixtures/fonts/mutatorsans-variable/MutatorSansBoldWide.ufo/glyphs/semicolon.glif @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/fixtures/fonts/mutatorsans-variable/MutatorSansBoldWide.ufo/glyphs/space.glif b/fixtures/fonts/mutatorsans-variable/MutatorSansBoldWide.ufo/glyphs/space.glif new file mode 100644 index 00000000..80c661f7 --- /dev/null +++ b/fixtures/fonts/mutatorsans-variable/MutatorSansBoldWide.ufo/glyphs/space.glif @@ -0,0 +1,7 @@ + + + + + + + diff --git a/fixtures/fonts/mutatorsans-variable/MutatorSansBoldWide.ufo/groups.plist b/fixtures/fonts/mutatorsans-variable/MutatorSansBoldWide.ufo/groups.plist new file mode 100644 index 00000000..7dc9fccd --- /dev/null +++ b/fixtures/fonts/mutatorsans-variable/MutatorSansBoldWide.ufo/groups.plist @@ -0,0 +1,20 @@ + + + + + public.kern1.@MMK_L_A + + A + + public.kern2.@MMK_R_A + + A + + testGroup + + E + F + H + + + diff --git a/fixtures/fonts/mutatorsans-variable/MutatorSansBoldWide.ufo/images/image.png b/fixtures/fonts/mutatorsans-variable/MutatorSansBoldWide.ufo/images/image.png new file mode 100644 index 00000000..1168dae6 Binary files /dev/null and b/fixtures/fonts/mutatorsans-variable/MutatorSansBoldWide.ufo/images/image.png differ diff --git a/fixtures/fonts/mutatorsans-variable/MutatorSansBoldWide.ufo/kerning.plist b/fixtures/fonts/mutatorsans-variable/MutatorSansBoldWide.ufo/kerning.plist new file mode 100644 index 00000000..1d469e77 --- /dev/null +++ b/fixtures/fonts/mutatorsans-variable/MutatorSansBoldWide.ufo/kerning.plist @@ -0,0 +1,11 @@ + + + + + T + + public.kern2.@MMK_R_A + -150 + + + diff --git a/fixtures/fonts/mutatorsans-variable/MutatorSansBoldWide.ufo/layercontents.plist b/fixtures/fonts/mutatorsans-variable/MutatorSansBoldWide.ufo/layercontents.plist new file mode 100644 index 00000000..e9a336b2 --- /dev/null +++ b/fixtures/fonts/mutatorsans-variable/MutatorSansBoldWide.ufo/layercontents.plist @@ -0,0 +1,14 @@ + + + + + + foreground + glyphs + + + background + glyphs.background + + + diff --git a/fixtures/fonts/mutatorsans-variable/MutatorSansBoldWide.ufo/lib.plist b/fixtures/fonts/mutatorsans-variable/MutatorSansBoldWide.ufo/lib.plist new file mode 100644 index 00000000..1a869874 --- /dev/null +++ b/fixtures/fonts/mutatorsans-variable/MutatorSansBoldWide.ufo/lib.plist @@ -0,0 +1,355 @@ + + + + + com.defcon.sortDescriptor + + + allowPseudoUnicode + + type + cannedDesign + + + com.letterror.lightMeter.prefs + + chunkSize + 5 + diameter + 200 + drawTail + + invert + + toolDiameter + 30 + toolStyle + fluid + + com.typemytype.robofont.background.layerStrokeColor + + 0.0 + 0.8 + 0.2 + 0.7 + + com.typemytype.robofont.compileSettings.autohint + + com.typemytype.robofont.compileSettings.checkOutlines + + com.typemytype.robofont.compileSettings.createDummyDSIG + + com.typemytype.robofont.compileSettings.decompose + + com.typemytype.robofont.compileSettings.generateFormat + 0 + com.typemytype.robofont.compileSettings.releaseMode + + com.typemytype.robofont.foreground.layerStrokeColor + + 0.5 + 0.0 + 0.5 + 0.7 + + com.typemytype.robofont.italicSlantOffset + 0 + com.typemytype.robofont.segmentType + curve + com.typemytype.robofont.shouldAddPointsInSplineConversion + 1 + com.typesupply.defcon.sortDescriptor + + + ascending + + space + A + Agrave + Aacute + Acircumflex + Atilde + Adieresis + Aring + B + C + Ccedilla + D + E + Egrave + Eacute + Ecircumflex + Edieresis + F + G + H + I + Igrave + Iacute + Icircumflex + Idieresis + J + K + L + M + N + Ntilde + O + Ograve + Oacute + Ocircumflex + Otilde + Odieresis + P + Q + R + S + Scaron + T + U + Ugrave + Uacute + Ucircumflex + Udieresis + V + W + X + Y + Yacute + Ydieresis + Z + Zcaron + AE + Eth + Oslash + Thorn + Lslash + OE + a + agrave + aacute + acircumflex + atilde + adieresis + aring + b + c + ccedilla + d + e + egrave + eacute + ecircumflex + edieresis + f + g + h + i + igrave + iacute + icircumflex + idieresis + j + k + l + m + n + ntilde + o + ograve + oacute + ocircumflex + otilde + odieresis + p + q + r + s + scaron + t + u + ugrave + uacute + ucircumflex + udieresis + v + w + x + y + yacute + ydieresis + z + zcaron + ordfeminine + ordmasculine + germandbls + ae + eth + oslash + thorn + dotlessi + lslash + oe + zero + one + two + three + four + five + six + seven + eight + nine + onesuperior + twosuperior + threesuperior + onequarter + onehalf + threequarters + underscore + hyphen + endash + emdash + parenleft + parenright + bracketleft + bracketright + braceleft + braceright + numbersign + percent + perthousand + quotesingle + quotedbl + quoteleft + quoteright + quotedblleft + quotedblright + quotesinglbase + quotedblbase + guilsinglleft + guilsinglright + guillemotleft + guillemotright + asterisk + dagger + daggerdbl + period + comma + colon + semicolon + ellipsis + exclam + exclamdown + question + questiondown + slash + backslash + fraction + bar + brokenbar + at + ampersand + section + paragraph + periodcentered + bullet + plus + minus + plusminus + divide + multiply + equal + less + greater + logicalnot + mu + dollar + cent + sterling + currency + yen + Euro + florin + asciicircum + asciitilde + acute + grave + hungarumlaut + circumflex + caron + breve + tilde + macron + dieresis + dotaccent + ring + cedilla + ogonek + copyright + registered + trademark + degree + fi + fl + .notdef + a_b_c + + type + glyphList + + + public.glyphOrder + + space + A + Aacute + Adieresis + B + C + D + E + F + G + H + I + J + K + L + M + N + O + P + Q + R + S + T + U + V + W + X + Y + Z + quotedblleft + quotedblright + quotesinglbase + quotedblbase + period + comma + colon + semicolon + dot + acute + dieresis + IJ + arrowdown + arrowleft + arrowright + arrowup + I.narrow + J.narrow + S.closed + .notdef + + + diff --git a/fixtures/fonts/mutatorsans-variable/MutatorSansBoldWide.ufo/metainfo.plist b/fixtures/fonts/mutatorsans-variable/MutatorSansBoldWide.ufo/metainfo.plist new file mode 100644 index 00000000..7b8b34ac --- /dev/null +++ b/fixtures/fonts/mutatorsans-variable/MutatorSansBoldWide.ufo/metainfo.plist @@ -0,0 +1,10 @@ + + + + + creator + com.github.fonttools.ufoLib + formatVersion + 3 + + diff --git a/fixtures/fonts/mutatorsans-variable/MutatorSansLightCondensed.ufo/features.fea b/fixtures/fonts/mutatorsans-variable/MutatorSansLightCondensed.ufo/features.fea new file mode 100644 index 00000000..81b14ace --- /dev/null +++ b/fixtures/fonts/mutatorsans-variable/MutatorSansLightCondensed.ufo/features.fea @@ -0,0 +1,4 @@ +# this is the feature from lightCondensed +# Hi_this_is_the_feature. +languagesystem DFLT dflt; +languagesystem latn dflt; diff --git a/fixtures/fonts/mutatorsans-variable/MutatorSansLightCondensed.ufo/fontinfo.plist b/fixtures/fonts/mutatorsans-variable/MutatorSansLightCondensed.ufo/fontinfo.plist new file mode 100644 index 00000000..d8dfd6fd --- /dev/null +++ b/fixtures/fonts/mutatorsans-variable/MutatorSansLightCondensed.ufo/fontinfo.plist @@ -0,0 +1,67 @@ + + + + + ascender + 700 + capHeight + 700 + copyright + License same as MutatorMath. BSD 3-clause. [test-token: C] + descender + -200 + familyName + MutatorSans + guidelines + + italicAngle + 0 + openTypeNameLicense + License same as MutatorMath. BSD 3-clause. [test-token: C] + openTypeOS2VendorID + LTTR + postscriptBlueValues + + -10 + 0 + 700 + 710 + + postscriptDefaultWidthX + 500 + postscriptFamilyBlues + + postscriptFamilyOtherBlues + + postscriptFontName + MutatorMathTest-LightCondensed + postscriptFullName + MutatorMathTest LightCondensed + postscriptOtherBlues + + postscriptSlantAngle + 0 + postscriptStemSnapH + + postscriptStemSnapV + + postscriptWindowsCharacterSet + 1 + styleMapFamilyName + + styleMapStyleName + regular + styleName + LightCondensed + unitsPerEm + 1000 + versionMajor + 1 + versionMinor + 2 + xHeight + 500 + year + 2004 + + diff --git a/fixtures/fonts/mutatorsans-variable/MutatorSansLightCondensed.ufo/glyphs.background/S_.closed.glif b/fixtures/fonts/mutatorsans-variable/MutatorSansLightCondensed.ufo/glyphs.background/S_.closed.glif new file mode 100644 index 00000000..260a24c2 --- /dev/null +++ b/fixtures/fonts/mutatorsans-variable/MutatorSansLightCondensed.ufo/glyphs.background/S_.closed.glif @@ -0,0 +1,98 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/fixtures/fonts/mutatorsans-variable/MutatorSansLightCondensed.ufo/glyphs.background/S_.glif b/fixtures/fonts/mutatorsans-variable/MutatorSansLightCondensed.ufo/glyphs.background/S_.glif new file mode 100644 index 00000000..ea1a7c6a --- /dev/null +++ b/fixtures/fonts/mutatorsans-variable/MutatorSansLightCondensed.ufo/glyphs.background/S_.glif @@ -0,0 +1,75 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + com.letterror.skateboard.navigator + + location + + weight + 820.0 + width + 1000 + + + com.typemytype.robofont.Image.Brightness + 0 + com.typemytype.robofont.Image.Contrast + 1 + com.typemytype.robofont.Image.Saturation + 1 + com.typemytype.robofont.Image.Sharpness + 0.4 + + + diff --git a/fixtures/fonts/mutatorsans-variable/MutatorSansLightCondensed.ufo/glyphs.background/contents.plist b/fixtures/fonts/mutatorsans-variable/MutatorSansLightCondensed.ufo/glyphs.background/contents.plist new file mode 100644 index 00000000..701b513a --- /dev/null +++ b/fixtures/fonts/mutatorsans-variable/MutatorSansLightCondensed.ufo/glyphs.background/contents.plist @@ -0,0 +1,10 @@ + + + + + S + S_.glif + S.closed + S_.closed.glif + + diff --git a/fixtures/fonts/mutatorsans-variable/MutatorSansLightCondensed.ufo/glyphs.background/layerinfo.plist b/fixtures/fonts/mutatorsans-variable/MutatorSansLightCondensed.ufo/glyphs.background/layerinfo.plist new file mode 100644 index 00000000..f3d8faef --- /dev/null +++ b/fixtures/fonts/mutatorsans-variable/MutatorSansLightCondensed.ufo/glyphs.background/layerinfo.plist @@ -0,0 +1,8 @@ + + + + + color + 0,1,1,0.7 + + diff --git a/fixtures/fonts/mutatorsans-variable/MutatorSansLightCondensed.ufo/glyphs.support.S_.middle/S_.closed.glif b/fixtures/fonts/mutatorsans-variable/MutatorSansLightCondensed.ufo/glyphs.support.S_.middle/S_.closed.glif new file mode 100644 index 00000000..16ae9f0b --- /dev/null +++ b/fixtures/fonts/mutatorsans-variable/MutatorSansLightCondensed.ufo/glyphs.support.S_.middle/S_.closed.glif @@ -0,0 +1,66 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + com.letterror.skateboard.navigator + + location + + weight + 700.0 + width + 569.078 + + + + + diff --git a/fixtures/fonts/mutatorsans-variable/MutatorSansLightCondensed.ufo/glyphs.support.S_.middle/contents.plist b/fixtures/fonts/mutatorsans-variable/MutatorSansLightCondensed.ufo/glyphs.support.S_.middle/contents.plist new file mode 100644 index 00000000..0ef1afc6 --- /dev/null +++ b/fixtures/fonts/mutatorsans-variable/MutatorSansLightCondensed.ufo/glyphs.support.S_.middle/contents.plist @@ -0,0 +1,8 @@ + + + + + S.closed + S_.closed.glif + + diff --git a/fixtures/fonts/mutatorsans-variable/MutatorSansLightCondensed.ufo/glyphs.support.S_.middle/layerinfo.plist b/fixtures/fonts/mutatorsans-variable/MutatorSansLightCondensed.ufo/glyphs.support.S_.middle/layerinfo.plist new file mode 100644 index 00000000..ea0e39cd --- /dev/null +++ b/fixtures/fonts/mutatorsans-variable/MutatorSansLightCondensed.ufo/glyphs.support.S_.middle/layerinfo.plist @@ -0,0 +1,8 @@ + + + + + color + 0.5,0,1,0.7 + + diff --git a/fixtures/fonts/mutatorsans-variable/MutatorSansLightCondensed.ufo/glyphs.support.S_.wide/S_.closed.glif b/fixtures/fonts/mutatorsans-variable/MutatorSansLightCondensed.ufo/glyphs.support.S_.wide/S_.closed.glif new file mode 100644 index 00000000..c33656eb --- /dev/null +++ b/fixtures/fonts/mutatorsans-variable/MutatorSansLightCondensed.ufo/glyphs.support.S_.wide/S_.closed.glif @@ -0,0 +1,66 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + com.letterror.skateboard.navigator + + location + + weight + 673.7998527960526 + width + 1000.0 + + + + + diff --git a/fixtures/fonts/mutatorsans-variable/MutatorSansLightCondensed.ufo/glyphs.support.S_.wide/S_.glif b/fixtures/fonts/mutatorsans-variable/MutatorSansLightCondensed.ufo/glyphs.support.S_.wide/S_.glif new file mode 100644 index 00000000..2abba517 --- /dev/null +++ b/fixtures/fonts/mutatorsans-variable/MutatorSansLightCondensed.ufo/glyphs.support.S_.wide/S_.glif @@ -0,0 +1,66 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + com.letterror.skateboard.navigator + + location + + weight + 759.5997715404774 + width + 1000.0 + + + + + diff --git a/fixtures/fonts/mutatorsans-variable/MutatorSansLightCondensed.ufo/glyphs.support.S_.wide/contents.plist b/fixtures/fonts/mutatorsans-variable/MutatorSansLightCondensed.ufo/glyphs.support.S_.wide/contents.plist new file mode 100644 index 00000000..701b513a --- /dev/null +++ b/fixtures/fonts/mutatorsans-variable/MutatorSansLightCondensed.ufo/glyphs.support.S_.wide/contents.plist @@ -0,0 +1,10 @@ + + + + + S + S_.glif + S.closed + S_.closed.glif + + diff --git a/fixtures/fonts/mutatorsans-variable/MutatorSansLightCondensed.ufo/glyphs.support.S_.wide/layerinfo.plist b/fixtures/fonts/mutatorsans-variable/MutatorSansLightCondensed.ufo/glyphs.support.S_.wide/layerinfo.plist new file mode 100644 index 00000000..9aafa333 --- /dev/null +++ b/fixtures/fonts/mutatorsans-variable/MutatorSansLightCondensed.ufo/glyphs.support.S_.wide/layerinfo.plist @@ -0,0 +1,8 @@ + + + + + color + 0,0.25,1,0.7 + + diff --git a/fixtures/fonts/mutatorsans-variable/MutatorSansLightCondensed.ufo/glyphs.support.crossbar/B_.glif b/fixtures/fonts/mutatorsans-variable/MutatorSansLightCondensed.ufo/glyphs.support.crossbar/B_.glif new file mode 100644 index 00000000..3f24fb62 --- /dev/null +++ b/fixtures/fonts/mutatorsans-variable/MutatorSansLightCondensed.ufo/glyphs.support.crossbar/B_.glif @@ -0,0 +1,63 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + com.letterror.skateboard.navigator + + location + + weight + 715.728 + width + -138.956 + + + + + diff --git a/fixtures/fonts/mutatorsans-variable/MutatorSansLightCondensed.ufo/glyphs.support.crossbar/E_.glif b/fixtures/fonts/mutatorsans-variable/MutatorSansLightCondensed.ufo/glyphs.support.crossbar/E_.glif new file mode 100644 index 00000000..ba5e5896 --- /dev/null +++ b/fixtures/fonts/mutatorsans-variable/MutatorSansLightCondensed.ufo/glyphs.support.crossbar/E_.glif @@ -0,0 +1,46 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + com.letterror.skateboard.navigator + + location + + weight + 715.728 + width + -138.956 + + + + + diff --git a/fixtures/fonts/mutatorsans-variable/MutatorSansLightCondensed.ufo/glyphs.support.crossbar/F_.glif b/fixtures/fonts/mutatorsans-variable/MutatorSansLightCondensed.ufo/glyphs.support.crossbar/F_.glif new file mode 100644 index 00000000..32fc9ad7 --- /dev/null +++ b/fixtures/fonts/mutatorsans-variable/MutatorSansLightCondensed.ufo/glyphs.support.crossbar/F_.glif @@ -0,0 +1,25 @@ + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/fixtures/fonts/mutatorsans-variable/MutatorSansLightCondensed.ufo/glyphs.support.crossbar/G_.glif b/fixtures/fonts/mutatorsans-variable/MutatorSansLightCondensed.ufo/glyphs.support.crossbar/G_.glif new file mode 100644 index 00000000..446a8ddf --- /dev/null +++ b/fixtures/fonts/mutatorsans-variable/MutatorSansLightCondensed.ufo/glyphs.support.crossbar/G_.glif @@ -0,0 +1,62 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + com.letterror.skateboard.navigator + + location + + weight + 715.728 + width + -138.956 + + + + + diff --git a/fixtures/fonts/mutatorsans-variable/MutatorSansLightCondensed.ufo/glyphs.support.crossbar/contents.plist b/fixtures/fonts/mutatorsans-variable/MutatorSansLightCondensed.ufo/glyphs.support.crossbar/contents.plist new file mode 100644 index 00000000..fc4dc072 --- /dev/null +++ b/fixtures/fonts/mutatorsans-variable/MutatorSansLightCondensed.ufo/glyphs.support.crossbar/contents.plist @@ -0,0 +1,14 @@ + + + + + B + B_.glif + E + E_.glif + F + F_.glif + G + G_.glif + + diff --git a/fixtures/fonts/mutatorsans-variable/MutatorSansLightCondensed.ufo/glyphs.support.crossbar/layerinfo.plist b/fixtures/fonts/mutatorsans-variable/MutatorSansLightCondensed.ufo/glyphs.support.crossbar/layerinfo.plist new file mode 100644 index 00000000..321e50a8 --- /dev/null +++ b/fixtures/fonts/mutatorsans-variable/MutatorSansLightCondensed.ufo/glyphs.support.crossbar/layerinfo.plist @@ -0,0 +1,8 @@ + + + + + color + 0,1,0.25,0.7 + + diff --git a/fixtures/fonts/mutatorsans-variable/MutatorSansLightCondensed.ufo/glyphs.support/A_.glif b/fixtures/fonts/mutatorsans-variable/MutatorSansLightCondensed.ufo/glyphs.support/A_.glif new file mode 100644 index 00000000..935df41d --- /dev/null +++ b/fixtures/fonts/mutatorsans-variable/MutatorSansLightCondensed.ufo/glyphs.support/A_.glif @@ -0,0 +1,31 @@ + + + + + + + + + com.letterror.skateboard.navigator + + location + + space + 0.0 + weight + 600.0 + width + 500.0 + + + com.typemytype.robofont.Image.Brightness + 0 + com.typemytype.robofont.Image.Contrast + 1 + com.typemytype.robofont.Image.Saturation + 1 + com.typemytype.robofont.Image.Sharpness + 0.4 + + + diff --git a/fixtures/fonts/mutatorsans-variable/MutatorSansLightCondensed.ufo/glyphs.support/S_.glif b/fixtures/fonts/mutatorsans-variable/MutatorSansLightCondensed.ufo/glyphs.support/S_.glif new file mode 100644 index 00000000..4aad20f6 --- /dev/null +++ b/fixtures/fonts/mutatorsans-variable/MutatorSansLightCondensed.ufo/glyphs.support/S_.glif @@ -0,0 +1,77 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + com.letterror.skateboard.navigator + + location + + space + 25.0 + weight + 707.6485770089287 + width + 181.31051199776795 + + + com.typemytype.robofont.Image.Brightness + 0 + com.typemytype.robofont.Image.Contrast + 1 + com.typemytype.robofont.Image.Saturation + 1 + com.typemytype.robofont.Image.Sharpness + 0.4 + + + diff --git a/fixtures/fonts/mutatorsans-variable/MutatorSansLightCondensed.ufo/glyphs.support/W_.glif b/fixtures/fonts/mutatorsans-variable/MutatorSansLightCondensed.ufo/glyphs.support/W_.glif new file mode 100644 index 00000000..06a4b755 --- /dev/null +++ b/fixtures/fonts/mutatorsans-variable/MutatorSansLightCondensed.ufo/glyphs.support/W_.glif @@ -0,0 +1,25 @@ + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/fixtures/fonts/mutatorsans-variable/MutatorSansLightCondensed.ufo/glyphs.support/contents.plist b/fixtures/fonts/mutatorsans-variable/MutatorSansLightCondensed.ufo/glyphs.support/contents.plist new file mode 100644 index 00000000..eb200c68 --- /dev/null +++ b/fixtures/fonts/mutatorsans-variable/MutatorSansLightCondensed.ufo/glyphs.support/contents.plist @@ -0,0 +1,12 @@ + + + + + A + A_.glif + S + S_.glif + W + W_.glif + + diff --git a/fixtures/fonts/mutatorsans-variable/MutatorSansLightCondensed.ufo/glyphs.support/layerinfo.plist b/fixtures/fonts/mutatorsans-variable/MutatorSansLightCondensed.ufo/glyphs.support/layerinfo.plist new file mode 100644 index 00000000..5ab4d3bc --- /dev/null +++ b/fixtures/fonts/mutatorsans-variable/MutatorSansLightCondensed.ufo/glyphs.support/layerinfo.plist @@ -0,0 +1,13 @@ + + + + + color + 0,1,0.25,0.7 + lib + + com.typemytype.robofont.segmentType + curve + + + diff --git a/fixtures/fonts/mutatorsans-variable/MutatorSansLightCondensed.ufo/glyphs/A_.glif b/fixtures/fonts/mutatorsans-variable/MutatorSansLightCondensed.ufo/glyphs/A_.glif new file mode 100644 index 00000000..a0de1496 --- /dev/null +++ b/fixtures/fonts/mutatorsans-variable/MutatorSansLightCondensed.ufo/glyphs/A_.glif @@ -0,0 +1,31 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/fixtures/fonts/mutatorsans-variable/MutatorSansLightCondensed.ufo/glyphs/A_acute.glif b/fixtures/fonts/mutatorsans-variable/MutatorSansLightCondensed.ufo/glyphs/A_acute.glif new file mode 100644 index 00000000..70645b1e --- /dev/null +++ b/fixtures/fonts/mutatorsans-variable/MutatorSansLightCondensed.ufo/glyphs/A_acute.glif @@ -0,0 +1,15 @@ + + + + + + + + + + + public.markColor + 0.6567,0.6903,1,1 + + + diff --git a/fixtures/fonts/mutatorsans-variable/MutatorSansLightCondensed.ufo/glyphs/A_dieresis.glif b/fixtures/fonts/mutatorsans-variable/MutatorSansLightCondensed.ufo/glyphs/A_dieresis.glif new file mode 100644 index 00000000..7b0e7d97 --- /dev/null +++ b/fixtures/fonts/mutatorsans-variable/MutatorSansLightCondensed.ufo/glyphs/A_dieresis.glif @@ -0,0 +1,15 @@ + + + + + + + + + + + public.markColor + 0.6567,0.6903,1,1 + + + diff --git a/fixtures/fonts/mutatorsans-variable/MutatorSansLightCondensed.ufo/glyphs/B_.glif b/fixtures/fonts/mutatorsans-variable/MutatorSansLightCondensed.ufo/glyphs/B_.glif new file mode 100644 index 00000000..b93e9a9f --- /dev/null +++ b/fixtures/fonts/mutatorsans-variable/MutatorSansLightCondensed.ufo/glyphs/B_.glif @@ -0,0 +1,49 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/fixtures/fonts/mutatorsans-variable/MutatorSansLightCondensed.ufo/glyphs/C_.glif b/fixtures/fonts/mutatorsans-variable/MutatorSansLightCondensed.ufo/glyphs/C_.glif new file mode 100644 index 00000000..46b3537b --- /dev/null +++ b/fixtures/fonts/mutatorsans-variable/MutatorSansLightCondensed.ufo/glyphs/C_.glif @@ -0,0 +1,39 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/fixtures/fonts/mutatorsans-variable/MutatorSansLightCondensed.ufo/glyphs/D_.glif b/fixtures/fonts/mutatorsans-variable/MutatorSansLightCondensed.ufo/glyphs/D_.glif new file mode 100644 index 00000000..6c02122d --- /dev/null +++ b/fixtures/fonts/mutatorsans-variable/MutatorSansLightCondensed.ufo/glyphs/D_.glif @@ -0,0 +1,33 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/fixtures/fonts/mutatorsans-variable/MutatorSansLightCondensed.ufo/glyphs/E_.glif b/fixtures/fonts/mutatorsans-variable/MutatorSansLightCondensed.ufo/glyphs/E_.glif new file mode 100644 index 00000000..a9b71bf6 --- /dev/null +++ b/fixtures/fonts/mutatorsans-variable/MutatorSansLightCondensed.ufo/glyphs/E_.glif @@ -0,0 +1,32 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/fixtures/fonts/mutatorsans-variable/MutatorSansLightCondensed.ufo/glyphs/F_.glif b/fixtures/fonts/mutatorsans-variable/MutatorSansLightCondensed.ufo/glyphs/F_.glif new file mode 100644 index 00000000..b9579326 --- /dev/null +++ b/fixtures/fonts/mutatorsans-variable/MutatorSansLightCondensed.ufo/glyphs/F_.glif @@ -0,0 +1,25 @@ + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/fixtures/fonts/mutatorsans-variable/MutatorSansLightCondensed.ufo/glyphs/G_.glif b/fixtures/fonts/mutatorsans-variable/MutatorSansLightCondensed.ufo/glyphs/G_.glif new file mode 100644 index 00000000..525fcc4b --- /dev/null +++ b/fixtures/fonts/mutatorsans-variable/MutatorSansLightCondensed.ufo/glyphs/G_.glif @@ -0,0 +1,48 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/fixtures/fonts/mutatorsans-variable/MutatorSansLightCondensed.ufo/glyphs/H_.glif b/fixtures/fonts/mutatorsans-variable/MutatorSansLightCondensed.ufo/glyphs/H_.glif new file mode 100644 index 00000000..e9431fda --- /dev/null +++ b/fixtures/fonts/mutatorsans-variable/MutatorSansLightCondensed.ufo/glyphs/H_.glif @@ -0,0 +1,25 @@ + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/fixtures/fonts/mutatorsans-variable/MutatorSansLightCondensed.ufo/glyphs/I_.glif b/fixtures/fonts/mutatorsans-variable/MutatorSansLightCondensed.ufo/glyphs/I_.glif new file mode 100644 index 00000000..58937754 --- /dev/null +++ b/fixtures/fonts/mutatorsans-variable/MutatorSansLightCondensed.ufo/glyphs/I_.glif @@ -0,0 +1,25 @@ + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/fixtures/fonts/mutatorsans-variable/MutatorSansLightCondensed.ufo/glyphs/I_.narrow.glif b/fixtures/fonts/mutatorsans-variable/MutatorSansLightCondensed.ufo/glyphs/I_.narrow.glif new file mode 100644 index 00000000..6ad5aa8a --- /dev/null +++ b/fixtures/fonts/mutatorsans-variable/MutatorSansLightCondensed.ufo/glyphs/I_.narrow.glif @@ -0,0 +1,24 @@ + + + + + + + + + + + + + + com.typemytype.robofont.Image.Brightness + 0 + com.typemytype.robofont.Image.Contrast + 1 + com.typemytype.robofont.Image.Saturation + 1 + com.typemytype.robofont.Image.Sharpness + 0.4 + + + diff --git a/fixtures/fonts/mutatorsans-variable/MutatorSansLightCondensed.ufo/glyphs/I_J_.glif b/fixtures/fonts/mutatorsans-variable/MutatorSansLightCondensed.ufo/glyphs/I_J_.glif new file mode 100644 index 00000000..72c2c50a --- /dev/null +++ b/fixtures/fonts/mutatorsans-variable/MutatorSansLightCondensed.ufo/glyphs/I_J_.glif @@ -0,0 +1,32 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/fixtures/fonts/mutatorsans-variable/MutatorSansLightCondensed.ufo/glyphs/J_.glif b/fixtures/fonts/mutatorsans-variable/MutatorSansLightCondensed.ufo/glyphs/J_.glif new file mode 100644 index 00000000..5347fe26 --- /dev/null +++ b/fixtures/fonts/mutatorsans-variable/MutatorSansLightCondensed.ufo/glyphs/J_.glif @@ -0,0 +1,27 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/fixtures/fonts/mutatorsans-variable/MutatorSansLightCondensed.ufo/glyphs/J_.narrow.glif b/fixtures/fonts/mutatorsans-variable/MutatorSansLightCondensed.ufo/glyphs/J_.narrow.glif new file mode 100644 index 00000000..8b094c92 --- /dev/null +++ b/fixtures/fonts/mutatorsans-variable/MutatorSansLightCondensed.ufo/glyphs/J_.narrow.glif @@ -0,0 +1,24 @@ + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/fixtures/fonts/mutatorsans-variable/MutatorSansLightCondensed.ufo/glyphs/K_.glif b/fixtures/fonts/mutatorsans-variable/MutatorSansLightCondensed.ufo/glyphs/K_.glif new file mode 100644 index 00000000..e871b0f9 --- /dev/null +++ b/fixtures/fonts/mutatorsans-variable/MutatorSansLightCondensed.ufo/glyphs/K_.glif @@ -0,0 +1,28 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/fixtures/fonts/mutatorsans-variable/MutatorSansLightCondensed.ufo/glyphs/L_.glif b/fixtures/fonts/mutatorsans-variable/MutatorSansLightCondensed.ufo/glyphs/L_.glif new file mode 100644 index 00000000..b8d8ce46 --- /dev/null +++ b/fixtures/fonts/mutatorsans-variable/MutatorSansLightCondensed.ufo/glyphs/L_.glif @@ -0,0 +1,19 @@ + + + + + + + + + + + + + + + + + + + diff --git a/fixtures/fonts/mutatorsans-variable/MutatorSansLightCondensed.ufo/glyphs/M_.glif b/fixtures/fonts/mutatorsans-variable/MutatorSansLightCondensed.ufo/glyphs/M_.glif new file mode 100644 index 00000000..e78048d7 --- /dev/null +++ b/fixtures/fonts/mutatorsans-variable/MutatorSansLightCondensed.ufo/glyphs/M_.glif @@ -0,0 +1,29 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/fixtures/fonts/mutatorsans-variable/MutatorSansLightCondensed.ufo/glyphs/N_.glif b/fixtures/fonts/mutatorsans-variable/MutatorSansLightCondensed.ufo/glyphs/N_.glif new file mode 100644 index 00000000..28771ffb --- /dev/null +++ b/fixtures/fonts/mutatorsans-variable/MutatorSansLightCondensed.ufo/glyphs/N_.glif @@ -0,0 +1,25 @@ + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/fixtures/fonts/mutatorsans-variable/MutatorSansLightCondensed.ufo/glyphs/O_.glif b/fixtures/fonts/mutatorsans-variable/MutatorSansLightCondensed.ufo/glyphs/O_.glif new file mode 100644 index 00000000..04bd4642 --- /dev/null +++ b/fixtures/fonts/mutatorsans-variable/MutatorSansLightCondensed.ufo/glyphs/O_.glif @@ -0,0 +1,39 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/fixtures/fonts/mutatorsans-variable/MutatorSansLightCondensed.ufo/glyphs/P_.glif b/fixtures/fonts/mutatorsans-variable/MutatorSansLightCondensed.ufo/glyphs/P_.glif new file mode 100644 index 00000000..5c13beba --- /dev/null +++ b/fixtures/fonts/mutatorsans-variable/MutatorSansLightCondensed.ufo/glyphs/P_.glif @@ -0,0 +1,33 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/fixtures/fonts/mutatorsans-variable/MutatorSansLightCondensed.ufo/glyphs/Q_.glif b/fixtures/fonts/mutatorsans-variable/MutatorSansLightCondensed.ufo/glyphs/Q_.glif new file mode 100644 index 00000000..17503c26 --- /dev/null +++ b/fixtures/fonts/mutatorsans-variable/MutatorSansLightCondensed.ufo/glyphs/Q_.glif @@ -0,0 +1,14 @@ + + + + + + + + + + + + + + diff --git a/fixtures/fonts/mutatorsans-variable/MutatorSansLightCondensed.ufo/glyphs/R_.glif b/fixtures/fonts/mutatorsans-variable/MutatorSansLightCondensed.ufo/glyphs/R_.glif new file mode 100644 index 00000000..8f0b2c9c --- /dev/null +++ b/fixtures/fonts/mutatorsans-variable/MutatorSansLightCondensed.ufo/glyphs/R_.glif @@ -0,0 +1,42 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/fixtures/fonts/mutatorsans-variable/MutatorSansLightCondensed.ufo/glyphs/S_.closed.glif b/fixtures/fonts/mutatorsans-variable/MutatorSansLightCondensed.ufo/glyphs/S_.closed.glif new file mode 100644 index 00000000..880efcdb --- /dev/null +++ b/fixtures/fonts/mutatorsans-variable/MutatorSansLightCondensed.ufo/glyphs/S_.closed.glif @@ -0,0 +1,52 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/fixtures/fonts/mutatorsans-variable/MutatorSansLightCondensed.ufo/glyphs/S_.glif b/fixtures/fonts/mutatorsans-variable/MutatorSansLightCondensed.ufo/glyphs/S_.glif new file mode 100644 index 00000000..a642d2c7 --- /dev/null +++ b/fixtures/fonts/mutatorsans-variable/MutatorSansLightCondensed.ufo/glyphs/S_.glif @@ -0,0 +1,65 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + com.typemytype.robofont.Image.Brightness + 0 + com.typemytype.robofont.Image.Contrast + 1 + com.typemytype.robofont.Image.Saturation + 1 + com.typemytype.robofont.Image.Sharpness + 0.4 + + + diff --git a/fixtures/fonts/mutatorsans-variable/MutatorSansLightCondensed.ufo/glyphs/T_.glif b/fixtures/fonts/mutatorsans-variable/MutatorSansLightCondensed.ufo/glyphs/T_.glif new file mode 100644 index 00000000..b4674b21 --- /dev/null +++ b/fixtures/fonts/mutatorsans-variable/MutatorSansLightCondensed.ufo/glyphs/T_.glif @@ -0,0 +1,18 @@ + + + + + + + + + + + + + + + + + + diff --git a/fixtures/fonts/mutatorsans-variable/MutatorSansLightCondensed.ufo/glyphs/U_.glif b/fixtures/fonts/mutatorsans-variable/MutatorSansLightCondensed.ufo/glyphs/U_.glif new file mode 100644 index 00000000..b2f892f7 --- /dev/null +++ b/fixtures/fonts/mutatorsans-variable/MutatorSansLightCondensed.ufo/glyphs/U_.glif @@ -0,0 +1,26 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/fixtures/fonts/mutatorsans-variable/MutatorSansLightCondensed.ufo/glyphs/V_.glif b/fixtures/fonts/mutatorsans-variable/MutatorSansLightCondensed.ufo/glyphs/V_.glif new file mode 100644 index 00000000..0c97296c --- /dev/null +++ b/fixtures/fonts/mutatorsans-variable/MutatorSansLightCondensed.ufo/glyphs/V_.glif @@ -0,0 +1,25 @@ + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/fixtures/fonts/mutatorsans-variable/MutatorSansLightCondensed.ufo/glyphs/W_.glif b/fixtures/fonts/mutatorsans-variable/MutatorSansLightCondensed.ufo/glyphs/W_.glif new file mode 100644 index 00000000..89434d65 --- /dev/null +++ b/fixtures/fonts/mutatorsans-variable/MutatorSansLightCondensed.ufo/glyphs/W_.glif @@ -0,0 +1,25 @@ + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/fixtures/fonts/mutatorsans-variable/MutatorSansLightCondensed.ufo/glyphs/X_.glif b/fixtures/fonts/mutatorsans-variable/MutatorSansLightCondensed.ufo/glyphs/X_.glif new file mode 100644 index 00000000..38bb129c --- /dev/null +++ b/fixtures/fonts/mutatorsans-variable/MutatorSansLightCondensed.ufo/glyphs/X_.glif @@ -0,0 +1,24 @@ + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/fixtures/fonts/mutatorsans-variable/MutatorSansLightCondensed.ufo/glyphs/Y_.glif b/fixtures/fonts/mutatorsans-variable/MutatorSansLightCondensed.ufo/glyphs/Y_.glif new file mode 100644 index 00000000..a42b73c5 --- /dev/null +++ b/fixtures/fonts/mutatorsans-variable/MutatorSansLightCondensed.ufo/glyphs/Y_.glif @@ -0,0 +1,36 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + com.typemytype.robofont.Image.Brightness + 0 + com.typemytype.robofont.Image.Contrast + 1 + com.typemytype.robofont.Image.Saturation + 1 + com.typemytype.robofont.Image.Sharpness + 0.4 + + + diff --git a/fixtures/fonts/mutatorsans-variable/MutatorSansLightCondensed.ufo/glyphs/Z_.glif b/fixtures/fonts/mutatorsans-variable/MutatorSansLightCondensed.ufo/glyphs/Z_.glif new file mode 100644 index 00000000..e9f15351 --- /dev/null +++ b/fixtures/fonts/mutatorsans-variable/MutatorSansLightCondensed.ufo/glyphs/Z_.glif @@ -0,0 +1,24 @@ + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/fixtures/fonts/mutatorsans-variable/MutatorSansLightCondensed.ufo/glyphs/_notdef.glif b/fixtures/fonts/mutatorsans-variable/MutatorSansLightCondensed.ufo/glyphs/_notdef.glif new file mode 100644 index 00000000..7bd7a779 --- /dev/null +++ b/fixtures/fonts/mutatorsans-variable/MutatorSansLightCondensed.ufo/glyphs/_notdef.glif @@ -0,0 +1,42 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + public.markColor + 0.6567,0.6903,1,1 + + + diff --git a/fixtures/fonts/mutatorsans-variable/MutatorSansLightCondensed.ufo/glyphs/acute.glif b/fixtures/fonts/mutatorsans-variable/MutatorSansLightCondensed.ufo/glyphs/acute.glif new file mode 100644 index 00000000..f6b2297f --- /dev/null +++ b/fixtures/fonts/mutatorsans-variable/MutatorSansLightCondensed.ufo/glyphs/acute.glif @@ -0,0 +1,13 @@ + + + + + + + + + + + + + diff --git a/fixtures/fonts/mutatorsans-variable/MutatorSansLightCondensed.ufo/glyphs/arrowdown.glif b/fixtures/fonts/mutatorsans-variable/MutatorSansLightCondensed.ufo/glyphs/arrowdown.glif new file mode 100644 index 00000000..7cc92fd1 --- /dev/null +++ b/fixtures/fonts/mutatorsans-variable/MutatorSansLightCondensed.ufo/glyphs/arrowdown.glif @@ -0,0 +1,24 @@ + + + + + + + + + + + + + + + + + + + + public.markColor + 0,0.95,0.95,1 + + + diff --git a/fixtures/fonts/mutatorsans-variable/MutatorSansLightCondensed.ufo/glyphs/arrowleft.glif b/fixtures/fonts/mutatorsans-variable/MutatorSansLightCondensed.ufo/glyphs/arrowleft.glif new file mode 100644 index 00000000..e8395a8c --- /dev/null +++ b/fixtures/fonts/mutatorsans-variable/MutatorSansLightCondensed.ufo/glyphs/arrowleft.glif @@ -0,0 +1,25 @@ + + + + + + + + + + + + + + + + + + + + + public.markColor + 0,0.95,0.95,1 + + + diff --git a/fixtures/fonts/mutatorsans-variable/MutatorSansLightCondensed.ufo/glyphs/arrowright.glif b/fixtures/fonts/mutatorsans-variable/MutatorSansLightCondensed.ufo/glyphs/arrowright.glif new file mode 100644 index 00000000..93e92c10 --- /dev/null +++ b/fixtures/fonts/mutatorsans-variable/MutatorSansLightCondensed.ufo/glyphs/arrowright.glif @@ -0,0 +1,24 @@ + + + + + + + + + + + + + + + + + + + + public.markColor + 0,0.95,0.95,1 + + + diff --git a/fixtures/fonts/mutatorsans-variable/MutatorSansLightCondensed.ufo/glyphs/arrowup.glif b/fixtures/fonts/mutatorsans-variable/MutatorSansLightCondensed.ufo/glyphs/arrowup.glif new file mode 100644 index 00000000..13f3a01e --- /dev/null +++ b/fixtures/fonts/mutatorsans-variable/MutatorSansLightCondensed.ufo/glyphs/arrowup.glif @@ -0,0 +1,24 @@ + + + + + + + + + + + + + + + + + + + + public.markColor + 0,0.95,0.95,1 + + + diff --git a/fixtures/fonts/mutatorsans-variable/MutatorSansLightCondensed.ufo/glyphs/b.glif b/fixtures/fonts/mutatorsans-variable/MutatorSansLightCondensed.ufo/glyphs/b.glif new file mode 100644 index 00000000..16accedd --- /dev/null +++ b/fixtures/fonts/mutatorsans-variable/MutatorSansLightCondensed.ufo/glyphs/b.glif @@ -0,0 +1,7 @@ + + + + + + + diff --git a/fixtures/fonts/mutatorsans-variable/MutatorSansLightCondensed.ufo/glyphs/c.glif b/fixtures/fonts/mutatorsans-variable/MutatorSansLightCondensed.ufo/glyphs/c.glif new file mode 100644 index 00000000..0b4b3ccf --- /dev/null +++ b/fixtures/fonts/mutatorsans-variable/MutatorSansLightCondensed.ufo/glyphs/c.glif @@ -0,0 +1,7 @@ + + + + + + + diff --git a/fixtures/fonts/mutatorsans-variable/MutatorSansLightCondensed.ufo/glyphs/colon.glif b/fixtures/fonts/mutatorsans-variable/MutatorSansLightCondensed.ufo/glyphs/colon.glif new file mode 100644 index 00000000..f9c7f8a7 --- /dev/null +++ b/fixtures/fonts/mutatorsans-variable/MutatorSansLightCondensed.ufo/glyphs/colon.glif @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/fixtures/fonts/mutatorsans-variable/MutatorSansLightCondensed.ufo/glyphs/comma.glif b/fixtures/fonts/mutatorsans-variable/MutatorSansLightCondensed.ufo/glyphs/comma.glif new file mode 100644 index 00000000..df2b5a61 --- /dev/null +++ b/fixtures/fonts/mutatorsans-variable/MutatorSansLightCondensed.ufo/glyphs/comma.glif @@ -0,0 +1,17 @@ + + + + + + + + + + + + + + + + + diff --git a/fixtures/fonts/mutatorsans-variable/MutatorSansLightCondensed.ufo/glyphs/contents.plist b/fixtures/fonts/mutatorsans-variable/MutatorSansLightCondensed.ufo/glyphs/contents.plist new file mode 100644 index 00000000..45273dee --- /dev/null +++ b/fixtures/fonts/mutatorsans-variable/MutatorSansLightCondensed.ufo/glyphs/contents.plist @@ -0,0 +1,104 @@ + + + + + .notdef + _notdef.glif + A + A_.glif + Aacute + A_acute.glif + Adieresis + A_dieresis.glif + B + B_.glif + C + C_.glif + D + D_.glif + E + E_.glif + F + F_.glif + G + G_.glif + H + H_.glif + I + I_.glif + I.narrow + I_.narrow.glif + IJ + I_J_.glif + J + J_.glif + J.narrow + J_.narrow.glif + K + K_.glif + L + L_.glif + M + M_.glif + N + N_.glif + O + O_.glif + P + P_.glif + Q + Q_.glif + R + R_.glif + S + S_.glif + S.closed + S_.closed.glif + T + T_.glif + U + U_.glif + V + V_.glif + W + W_.glif + X + X_.glif + Y + Y_.glif + Z + Z_.glif + acute + acute.glif + arrowdown + arrowdown.glif + arrowleft + arrowleft.glif + arrowright + arrowright.glif + arrowup + arrowup.glif + colon + colon.glif + comma + comma.glif + dieresis + dieresis.glif + dot + dot.glif + period + period.glif + quotedblbase + quotedblbase.glif + quotedblleft + quotedblleft.glif + quotedblright + quotedblright.glif + quotesinglbase + quotesinglbase.glif + semicolon + semicolon.glif + space + space.glif + + diff --git a/fixtures/fonts/mutatorsans-variable/MutatorSansLightCondensed.ufo/glyphs/d.glif b/fixtures/fonts/mutatorsans-variable/MutatorSansLightCondensed.ufo/glyphs/d.glif new file mode 100644 index 00000000..8fc09610 --- /dev/null +++ b/fixtures/fonts/mutatorsans-variable/MutatorSansLightCondensed.ufo/glyphs/d.glif @@ -0,0 +1,7 @@ + + + + + + + diff --git a/fixtures/fonts/mutatorsans-variable/MutatorSansLightCondensed.ufo/glyphs/dieresis.glif b/fixtures/fonts/mutatorsans-variable/MutatorSansLightCondensed.ufo/glyphs/dieresis.glif new file mode 100644 index 00000000..765ef4c5 --- /dev/null +++ b/fixtures/fonts/mutatorsans-variable/MutatorSansLightCondensed.ufo/glyphs/dieresis.glif @@ -0,0 +1,15 @@ + + + + + + + + + + + public.markColor + 0.6567,0.6903,1,1 + + + diff --git a/fixtures/fonts/mutatorsans-variable/MutatorSansLightCondensed.ufo/glyphs/dot.glif b/fixtures/fonts/mutatorsans-variable/MutatorSansLightCondensed.ufo/glyphs/dot.glif new file mode 100644 index 00000000..8f14d475 --- /dev/null +++ b/fixtures/fonts/mutatorsans-variable/MutatorSansLightCondensed.ufo/glyphs/dot.glif @@ -0,0 +1,13 @@ + + + + + + + + + + + + + diff --git a/fixtures/fonts/mutatorsans-variable/MutatorSansLightCondensed.ufo/glyphs/layerinfo.plist b/fixtures/fonts/mutatorsans-variable/MutatorSansLightCondensed.ufo/glyphs/layerinfo.plist new file mode 100644 index 00000000..aeeb1b2a --- /dev/null +++ b/fixtures/fonts/mutatorsans-variable/MutatorSansLightCondensed.ufo/glyphs/layerinfo.plist @@ -0,0 +1,13 @@ + + + + + color + 1,0.75,0,0.7 + lib + + com.typemytype.robofont.segmentType + curve + + + diff --git a/fixtures/fonts/mutatorsans-variable/MutatorSansLightCondensed.ufo/glyphs/period.glif b/fixtures/fonts/mutatorsans-variable/MutatorSansLightCondensed.ufo/glyphs/period.glif new file mode 100644 index 00000000..76242499 --- /dev/null +++ b/fixtures/fonts/mutatorsans-variable/MutatorSansLightCondensed.ufo/glyphs/period.glif @@ -0,0 +1,13 @@ + + + + + + + + + + + + + diff --git a/fixtures/fonts/mutatorsans-variable/MutatorSansLightCondensed.ufo/glyphs/quotedblbase.glif b/fixtures/fonts/mutatorsans-variable/MutatorSansLightCondensed.ufo/glyphs/quotedblbase.glif new file mode 100644 index 00000000..5a007a80 --- /dev/null +++ b/fixtures/fonts/mutatorsans-variable/MutatorSansLightCondensed.ufo/glyphs/quotedblbase.glif @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/fixtures/fonts/mutatorsans-variable/MutatorSansLightCondensed.ufo/glyphs/quotedblleft.glif b/fixtures/fonts/mutatorsans-variable/MutatorSansLightCondensed.ufo/glyphs/quotedblleft.glif new file mode 100644 index 00000000..528a8ab8 --- /dev/null +++ b/fixtures/fonts/mutatorsans-variable/MutatorSansLightCondensed.ufo/glyphs/quotedblleft.glif @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/fixtures/fonts/mutatorsans-variable/MutatorSansLightCondensed.ufo/glyphs/quotedblright.glif b/fixtures/fonts/mutatorsans-variable/MutatorSansLightCondensed.ufo/glyphs/quotedblright.glif new file mode 100644 index 00000000..42feceea --- /dev/null +++ b/fixtures/fonts/mutatorsans-variable/MutatorSansLightCondensed.ufo/glyphs/quotedblright.glif @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/fixtures/fonts/mutatorsans-variable/MutatorSansLightCondensed.ufo/glyphs/quotesinglbase.glif b/fixtures/fonts/mutatorsans-variable/MutatorSansLightCondensed.ufo/glyphs/quotesinglbase.glif new file mode 100644 index 00000000..a451b737 --- /dev/null +++ b/fixtures/fonts/mutatorsans-variable/MutatorSansLightCondensed.ufo/glyphs/quotesinglbase.glif @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/fixtures/fonts/mutatorsans-variable/MutatorSansLightCondensed.ufo/glyphs/semicolon.glif b/fixtures/fonts/mutatorsans-variable/MutatorSansLightCondensed.ufo/glyphs/semicolon.glif new file mode 100644 index 00000000..2140efd3 --- /dev/null +++ b/fixtures/fonts/mutatorsans-variable/MutatorSansLightCondensed.ufo/glyphs/semicolon.glif @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/fixtures/fonts/mutatorsans-variable/MutatorSansLightCondensed.ufo/glyphs/space.glif b/fixtures/fonts/mutatorsans-variable/MutatorSansLightCondensed.ufo/glyphs/space.glif new file mode 100644 index 00000000..80c661f7 --- /dev/null +++ b/fixtures/fonts/mutatorsans-variable/MutatorSansLightCondensed.ufo/glyphs/space.glif @@ -0,0 +1,7 @@ + + + + + + + diff --git a/fixtures/fonts/mutatorsans-variable/MutatorSansLightCondensed.ufo/groups.plist b/fixtures/fonts/mutatorsans-variable/MutatorSansLightCondensed.ufo/groups.plist new file mode 100644 index 00000000..7dc9fccd --- /dev/null +++ b/fixtures/fonts/mutatorsans-variable/MutatorSansLightCondensed.ufo/groups.plist @@ -0,0 +1,20 @@ + + + + + public.kern1.@MMK_L_A + + A + + public.kern2.@MMK_R_A + + A + + testGroup + + E + F + H + + + diff --git a/fixtures/fonts/mutatorsans-variable/MutatorSansLightCondensed.ufo/images/image b/fixtures/fonts/mutatorsans-variable/MutatorSansLightCondensed.ufo/images/image new file mode 100644 index 00000000..965d6cdc Binary files /dev/null and b/fixtures/fonts/mutatorsans-variable/MutatorSansLightCondensed.ufo/images/image differ diff --git a/fixtures/fonts/mutatorsans-variable/MutatorSansLightCondensed.ufo/images/image000000000000001 b/fixtures/fonts/mutatorsans-variable/MutatorSansLightCondensed.ufo/images/image000000000000001 new file mode 100644 index 00000000..214772c4 Binary files /dev/null and b/fixtures/fonts/mutatorsans-variable/MutatorSansLightCondensed.ufo/images/image000000000000001 differ diff --git a/fixtures/fonts/mutatorsans-variable/MutatorSansLightCondensed.ufo/kerning.plist b/fixtures/fonts/mutatorsans-variable/MutatorSansLightCondensed.ufo/kerning.plist new file mode 100644 index 00000000..f88f6c0b --- /dev/null +++ b/fixtures/fonts/mutatorsans-variable/MutatorSansLightCondensed.ufo/kerning.plist @@ -0,0 +1,21 @@ + + + + + T + + public.kern2.@MMK_R_A + -75 + + V + + public.kern2.@MMK_R_A + -100 + + public.kern1.@MMK_L_A + + V + -15 + + + diff --git a/fixtures/fonts/mutatorsans-variable/MutatorSansLightCondensed.ufo/layercontents.plist b/fixtures/fonts/mutatorsans-variable/MutatorSansLightCondensed.ufo/layercontents.plist new file mode 100644 index 00000000..c2622431 --- /dev/null +++ b/fixtures/fonts/mutatorsans-variable/MutatorSansLightCondensed.ufo/layercontents.plist @@ -0,0 +1,30 @@ + + + + + + foreground + glyphs + + + support + glyphs.support + + + support.crossbar + glyphs.support.crossbar + + + background + glyphs.background + + + support.S.wide + glyphs.support.S_.wide + + + support.S.middle + glyphs.support.S_.middle + + + diff --git a/fixtures/fonts/mutatorsans-variable/MutatorSansLightCondensed.ufo/lib.plist b/fixtures/fonts/mutatorsans-variable/MutatorSansLightCondensed.ufo/lib.plist new file mode 100644 index 00000000..e8c27f6c --- /dev/null +++ b/fixtures/fonts/mutatorsans-variable/MutatorSansLightCondensed.ufo/lib.plist @@ -0,0 +1,644 @@ + + + + + com.defcon.sortDescriptor + + + allowPseudoUnicode + + type + cannedDesign + + + com.letterror.lightMeter.prefs + + chunkSize + 5 + diameter + 200 + drawTail + + invert + + toolDiameter + 30 + toolStyle + fluid + + com.typemytype.robofont.background.layerStrokeColor + + 0.0 + 0.8 + 0.2 + 0.7 + + com.typemytype.robofont.compileSettings.autohint + + com.typemytype.robofont.compileSettings.checkOutlines + + com.typemytype.robofont.compileSettings.createDummyDSIG + + com.typemytype.robofont.compileSettings.decompose + + com.typemytype.robofont.compileSettings.generateFormat + 0 + com.typemytype.robofont.compileSettings.releaseMode + + com.typemytype.robofont.foreground.layerStrokeColor + + 0.5 + 0.0 + 0.5 + 0.7 + + com.typemytype.robofont.italicSlantOffset + 0 + com.typemytype.robofont.segmentType + curve + com.typemytype.robofont.shouldAddPointsInSplineConversion + 1 + com.typesupply.MetricsMachine4.groupColors + + @MMK_L_A + + 1.0 + 0.0 + 0.0 + 0.25 + + @MMK_L_C + + 1.0 + 0.5 + 0.0 + 0.25 + + @MMK_L_E + + 1.0 + 1.0 + 0.0 + 0.25 + + @MMK_L_I + + 0.0 + 1.0 + 0.0 + 0.25 + + @MMK_L_N + + 0.0 + 1.0 + 1.0 + 0.25 + + @MMK_L_O + + 0.0 + 0.5 + 1.0 + 0.25 + + @MMK_L_S + + 0.0 + 0.0 + 1.0 + 0.25 + + @MMK_L_U + + 0.5 + 0.0 + 1.0 + 0.25 + + @MMK_L_Y + + 1.0 + 0.0 + 1.0 + 0.25 + + @MMK_L_Z + + 1.0 + 0.0 + 0.5 + 0.25 + + @MMK_L_a + + 1.0 + 0.0 + 0.0 + 0.25 + + @MMK_L_c + + 1.0 + 0.5 + 0.0 + 0.25 + + @MMK_L_e + + 1.0 + 1.0 + 0.0 + 0.25 + + @MMK_L_i + + 0.0 + 1.0 + 0.0 + 0.25 + + @MMK_L_n + + 0.0 + 1.0 + 1.0 + 0.25 + + @MMK_L_o + + 0.0 + 0.5 + 1.0 + 0.25 + + @MMK_L_s + + 0.0 + 0.0 + 1.0 + 0.25 + + @MMK_L_u + + 0.5 + 0.0 + 1.0 + 0.25 + + @MMK_L_y + + 1.0 + 0.0 + 1.0 + 0.25 + + @MMK_L_z + + 1.0 + 0.0 + 0.5 + 0.25 + + @MMK_R_A + + 1.0 + 0.0 + 0.0 + 0.25 + + @MMK_R_C + + 1.0 + 0.5 + 0.0 + 0.25 + + @MMK_R_E + + 1.0 + 1.0 + 0.0 + 0.25 + + @MMK_R_I + + 0.0 + 1.0 + 0.0 + 0.25 + + @MMK_R_N + + 0.0 + 1.0 + 1.0 + 0.25 + + @MMK_R_O + + 0.0 + 0.5 + 1.0 + 0.25 + + @MMK_R_S + + 0.0 + 0.0 + 1.0 + 0.25 + + @MMK_R_U + + 0.5 + 0.0 + 1.0 + 0.25 + + @MMK_R_Y + + 1.0 + 0.0 + 1.0 + 0.25 + + @MMK_R_Z + + 1.0 + 0.0 + 0.5 + 0.25 + + @MMK_R_a + + 1.0 + 0.0 + 0.0 + 0.25 + + @MMK_R_c + + 1.0 + 0.5 + 0.0 + 0.25 + + @MMK_R_e + + 1.0 + 1.0 + 0.0 + 0.25 + + @MMK_R_i + + 0.0 + 1.0 + 0.0 + 0.25 + + @MMK_R_n + + 0.0 + 1.0 + 1.0 + 0.25 + + @MMK_R_o + + 0.0 + 0.5 + 1.0 + 0.25 + + @MMK_R_s + + 0.0 + 0.0 + 1.0 + 0.25 + + @MMK_R_u + + 0.5 + 0.0 + 1.0 + 0.25 + + @MMK_R_y + + 1.0 + 0.0 + 1.0 + 0.25 + + @MMK_R_z + + 1.0 + 0.0 + 0.5 + 0.25 + + + com.typesupply.defcon.sortDescriptor + + + ascending + + space + A + Agrave + Aacute + Acircumflex + Atilde + Adieresis + Aring + B + C + Ccedilla + D + E + Egrave + Eacute + Ecircumflex + Edieresis + F + G + H + I + Igrave + Iacute + Icircumflex + Idieresis + J + K + L + M + N + Ntilde + O + Ograve + Oacute + Ocircumflex + Otilde + Odieresis + P + Q + R + S + Scaron + T + U + Ugrave + Uacute + Ucircumflex + Udieresis + V + W + X + Y + Yacute + Ydieresis + Z + Zcaron + AE + Eth + Oslash + Thorn + Lslash + OE + a + agrave + aacute + acircumflex + atilde + adieresis + aring + b + c + ccedilla + d + e + egrave + eacute + ecircumflex + edieresis + f + g + h + i + igrave + iacute + icircumflex + idieresis + j + k + l + m + n + ntilde + o + ograve + oacute + ocircumflex + otilde + odieresis + p + q + r + s + scaron + t + u + ugrave + uacute + ucircumflex + udieresis + v + w + x + y + yacute + ydieresis + z + zcaron + ordfeminine + ordmasculine + germandbls + ae + eth + oslash + thorn + dotlessi + lslash + oe + mu + zero + one + two + three + four + five + six + seven + eight + nine + onesuperior + twosuperior + threesuperior + onequarter + onehalf + threequarters + underscore + hyphen + endash + emdash + parenleft + parenright + bracketleft + bracketright + braceleft + braceright + numbersign + percent + perthousand + quotesingle + quotedbl + quoteleft + quoteright + quotedblleft + quotedblright + quotesinglbase + quotedblbase + guilsinglleft + guilsinglright + asterisk + dagger + daggerdbl + period + comma + colon + semicolon + ellipsis + exclam + exclamdown + question + questiondown + slash + backslash + fraction + bar + brokenbar + at + ampersand + section + paragraph + periodcentered + bullet + plus + minus + plusminus + divide + multiply + equal + less + greater + logicalnot + dollar + cent + sterling + currency + yen + Euro + asciicircum + asciitilde + acute + grave + hungarumlaut + circumflex + caron + breve + tilde + macron + dieresis + dotaccent + ring + cedilla + ogonek + copyright + registered + trademark + degree + florin + guillemotleft + guillemotright + fi + fl + a_b_c + .notdef + + type + glyphList + + + public.glyphOrder + + space + A + Aacute + Adieresis + B + C + D + E + F + G + H + I + J + K + L + M + N + O + P + Q + R + S + T + U + V + W + X + Y + Z + quotedblleft + quotedblright + quotesinglbase + quotedblbase + period + comma + colon + semicolon + arrowleft + arrowup + arrowright + arrowdown + dot + acute + dieresis + IJ + I.narrow + J.narrow + S.closed + .notdef + + testLibItemKey + + a + b + c + + + diff --git a/fixtures/fonts/mutatorsans-variable/MutatorSansLightCondensed.ufo/metainfo.plist b/fixtures/fonts/mutatorsans-variable/MutatorSansLightCondensed.ufo/metainfo.plist new file mode 100644 index 00000000..7b8b34ac --- /dev/null +++ b/fixtures/fonts/mutatorsans-variable/MutatorSansLightCondensed.ufo/metainfo.plist @@ -0,0 +1,10 @@ + + + + + creator + com.github.fonttools.ufoLib + formatVersion + 3 + + diff --git a/fixtures/fonts/mutatorsans-variable/MutatorSansLightWide.ufo/features.fea b/fixtures/fonts/mutatorsans-variable/MutatorSansLightWide.ufo/features.fea new file mode 100644 index 00000000..124776d7 --- /dev/null +++ b/fixtures/fonts/mutatorsans-variable/MutatorSansLightWide.ufo/features.fea @@ -0,0 +1,3 @@ +# this is the feature from lightWide +languagesystem DFLT dflt; +languagesystem latn dflt; diff --git a/fixtures/fonts/mutatorsans-variable/MutatorSansLightWide.ufo/fontinfo.plist b/fixtures/fonts/mutatorsans-variable/MutatorSansLightWide.ufo/fontinfo.plist new file mode 100644 index 00000000..222803ff --- /dev/null +++ b/fixtures/fonts/mutatorsans-variable/MutatorSansLightWide.ufo/fontinfo.plist @@ -0,0 +1,65 @@ + + + + + ascender + 700 + capHeight + 700 + copyright + License same as MutatorMath. BSD 3-clause. [test-token: D] + descender + -200 + familyName + MutatorSans + guidelines + + italicAngle + 0 + openTypeNameLicense + License same as MutatorMath. BSD 3-clause. [test-token: D] + openTypeOS2VendorID + LTTR + postscriptBlueValues + + -10 + 0 + 700 + 710 + + postscriptDefaultWidthX + 500 + postscriptFamilyBlues + + postscriptFamilyOtherBlues + + postscriptFontName + MutatorSans-LightWide + postscriptOtherBlues + + postscriptSlantAngle + 0 + postscriptStemSnapH + + postscriptStemSnapV + + postscriptWindowsCharacterSet + 1 + styleMapFamilyName + + styleMapStyleName + regular + styleName + LightWide + unitsPerEm + 1000 + versionMajor + 1 + versionMinor + 2 + xHeight + 500 + year + 2004 + + diff --git a/fixtures/fonts/mutatorsans-variable/MutatorSansLightWide.ufo/glyphs.background/S_.closed.glif b/fixtures/fonts/mutatorsans-variable/MutatorSansLightWide.ufo/glyphs.background/S_.closed.glif new file mode 100644 index 00000000..8ad86c9b --- /dev/null +++ b/fixtures/fonts/mutatorsans-variable/MutatorSansLightWide.ufo/glyphs.background/S_.closed.glif @@ -0,0 +1,52 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/fixtures/fonts/mutatorsans-variable/MutatorSansLightWide.ufo/glyphs.background/contents.plist b/fixtures/fonts/mutatorsans-variable/MutatorSansLightWide.ufo/glyphs.background/contents.plist new file mode 100644 index 00000000..0ef1afc6 --- /dev/null +++ b/fixtures/fonts/mutatorsans-variable/MutatorSansLightWide.ufo/glyphs.background/contents.plist @@ -0,0 +1,8 @@ + + + + + S.closed + S_.closed.glif + + diff --git a/fixtures/fonts/mutatorsans-variable/MutatorSansLightWide.ufo/glyphs.background/layerinfo.plist b/fixtures/fonts/mutatorsans-variable/MutatorSansLightWide.ufo/glyphs.background/layerinfo.plist new file mode 100644 index 00000000..7e385c7f --- /dev/null +++ b/fixtures/fonts/mutatorsans-variable/MutatorSansLightWide.ufo/glyphs.background/layerinfo.plist @@ -0,0 +1,8 @@ + + + + + color + 0.5,1,0,0.7 + + diff --git a/fixtures/fonts/mutatorsans-variable/MutatorSansLightWide.ufo/glyphs/A_.glif b/fixtures/fonts/mutatorsans-variable/MutatorSansLightWide.ufo/glyphs/A_.glif new file mode 100644 index 00000000..9bda24f8 --- /dev/null +++ b/fixtures/fonts/mutatorsans-variable/MutatorSansLightWide.ufo/glyphs/A_.glif @@ -0,0 +1,43 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + com.typemytype.robofont.Image.Brightness + 0 + com.typemytype.robofont.Image.Contrast + 1 + com.typemytype.robofont.Image.Saturation + 1 + com.typemytype.robofont.Image.Sharpness + 0.4 + + + diff --git a/fixtures/fonts/mutatorsans-variable/MutatorSansLightWide.ufo/glyphs/A_acute.glif b/fixtures/fonts/mutatorsans-variable/MutatorSansLightWide.ufo/glyphs/A_acute.glif new file mode 100644 index 00000000..cf8ade0e --- /dev/null +++ b/fixtures/fonts/mutatorsans-variable/MutatorSansLightWide.ufo/glyphs/A_acute.glif @@ -0,0 +1,15 @@ + + + + + + + + + + + public.markColor + 0.6567,0.6903,1,1 + + + diff --git a/fixtures/fonts/mutatorsans-variable/MutatorSansLightWide.ufo/glyphs/A_dieresis.glif b/fixtures/fonts/mutatorsans-variable/MutatorSansLightWide.ufo/glyphs/A_dieresis.glif new file mode 100644 index 00000000..64d419b2 --- /dev/null +++ b/fixtures/fonts/mutatorsans-variable/MutatorSansLightWide.ufo/glyphs/A_dieresis.glif @@ -0,0 +1,15 @@ + + + + + + + + + + + public.markColor + 0.6567,0.6903,1,1 + + + diff --git a/fixtures/fonts/mutatorsans-variable/MutatorSansLightWide.ufo/glyphs/B_.glif b/fixtures/fonts/mutatorsans-variable/MutatorSansLightWide.ufo/glyphs/B_.glif new file mode 100644 index 00000000..2df4bd12 --- /dev/null +++ b/fixtures/fonts/mutatorsans-variable/MutatorSansLightWide.ufo/glyphs/B_.glif @@ -0,0 +1,49 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/fixtures/fonts/mutatorsans-variable/MutatorSansLightWide.ufo/glyphs/C_.glif b/fixtures/fonts/mutatorsans-variable/MutatorSansLightWide.ufo/glyphs/C_.glif new file mode 100644 index 00000000..dfe52541 --- /dev/null +++ b/fixtures/fonts/mutatorsans-variable/MutatorSansLightWide.ufo/glyphs/C_.glif @@ -0,0 +1,39 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/fixtures/fonts/mutatorsans-variable/MutatorSansLightWide.ufo/glyphs/D_.glif b/fixtures/fonts/mutatorsans-variable/MutatorSansLightWide.ufo/glyphs/D_.glif new file mode 100644 index 00000000..7aab614c --- /dev/null +++ b/fixtures/fonts/mutatorsans-variable/MutatorSansLightWide.ufo/glyphs/D_.glif @@ -0,0 +1,33 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/fixtures/fonts/mutatorsans-variable/MutatorSansLightWide.ufo/glyphs/E_.glif b/fixtures/fonts/mutatorsans-variable/MutatorSansLightWide.ufo/glyphs/E_.glif new file mode 100644 index 00000000..201d0def --- /dev/null +++ b/fixtures/fonts/mutatorsans-variable/MutatorSansLightWide.ufo/glyphs/E_.glif @@ -0,0 +1,44 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + com.typemytype.robofont.Image.Brightness + 0 + com.typemytype.robofont.Image.Contrast + 1 + com.typemytype.robofont.Image.Saturation + 1 + com.typemytype.robofont.Image.Sharpness + 0.4 + + + diff --git a/fixtures/fonts/mutatorsans-variable/MutatorSansLightWide.ufo/glyphs/F_.glif b/fixtures/fonts/mutatorsans-variable/MutatorSansLightWide.ufo/glyphs/F_.glif new file mode 100644 index 00000000..f1e68b8f --- /dev/null +++ b/fixtures/fonts/mutatorsans-variable/MutatorSansLightWide.ufo/glyphs/F_.glif @@ -0,0 +1,32 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + com.typemytype.robofont.guideline.magnetic.tCW6w1QdWl + 5 + + + diff --git a/fixtures/fonts/mutatorsans-variable/MutatorSansLightWide.ufo/glyphs/G_.glif b/fixtures/fonts/mutatorsans-variable/MutatorSansLightWide.ufo/glyphs/G_.glif new file mode 100644 index 00000000..f15c562d --- /dev/null +++ b/fixtures/fonts/mutatorsans-variable/MutatorSansLightWide.ufo/glyphs/G_.glif @@ -0,0 +1,48 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/fixtures/fonts/mutatorsans-variable/MutatorSansLightWide.ufo/glyphs/H_.glif b/fixtures/fonts/mutatorsans-variable/MutatorSansLightWide.ufo/glyphs/H_.glif new file mode 100644 index 00000000..e6f12e3c --- /dev/null +++ b/fixtures/fonts/mutatorsans-variable/MutatorSansLightWide.ufo/glyphs/H_.glif @@ -0,0 +1,25 @@ + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/fixtures/fonts/mutatorsans-variable/MutatorSansLightWide.ufo/glyphs/I_.glif b/fixtures/fonts/mutatorsans-variable/MutatorSansLightWide.ufo/glyphs/I_.glif new file mode 100644 index 00000000..fa3c5a78 --- /dev/null +++ b/fixtures/fonts/mutatorsans-variable/MutatorSansLightWide.ufo/glyphs/I_.glif @@ -0,0 +1,25 @@ + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/fixtures/fonts/mutatorsans-variable/MutatorSansLightWide.ufo/glyphs/I_.narrow.glif b/fixtures/fonts/mutatorsans-variable/MutatorSansLightWide.ufo/glyphs/I_.narrow.glif new file mode 100644 index 00000000..fdf59866 --- /dev/null +++ b/fixtures/fonts/mutatorsans-variable/MutatorSansLightWide.ufo/glyphs/I_.narrow.glif @@ -0,0 +1,24 @@ + + + + + + + + + + + + + + com.typemytype.robofont.Image.Brightness + 0 + com.typemytype.robofont.Image.Contrast + 1 + com.typemytype.robofont.Image.Saturation + 1 + com.typemytype.robofont.Image.Sharpness + 0.4 + + + diff --git a/fixtures/fonts/mutatorsans-variable/MutatorSansLightWide.ufo/glyphs/I_J_.glif b/fixtures/fonts/mutatorsans-variable/MutatorSansLightWide.ufo/glyphs/I_J_.glif new file mode 100644 index 00000000..1b8dc0d9 --- /dev/null +++ b/fixtures/fonts/mutatorsans-variable/MutatorSansLightWide.ufo/glyphs/I_J_.glif @@ -0,0 +1,32 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/fixtures/fonts/mutatorsans-variable/MutatorSansLightWide.ufo/glyphs/J_.glif b/fixtures/fonts/mutatorsans-variable/MutatorSansLightWide.ufo/glyphs/J_.glif new file mode 100644 index 00000000..5c9c0927 --- /dev/null +++ b/fixtures/fonts/mutatorsans-variable/MutatorSansLightWide.ufo/glyphs/J_.glif @@ -0,0 +1,27 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/fixtures/fonts/mutatorsans-variable/MutatorSansLightWide.ufo/glyphs/J_.narrow.glif b/fixtures/fonts/mutatorsans-variable/MutatorSansLightWide.ufo/glyphs/J_.narrow.glif new file mode 100644 index 00000000..9d39b581 --- /dev/null +++ b/fixtures/fonts/mutatorsans-variable/MutatorSansLightWide.ufo/glyphs/J_.narrow.glif @@ -0,0 +1,24 @@ + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/fixtures/fonts/mutatorsans-variable/MutatorSansLightWide.ufo/glyphs/K_.glif b/fixtures/fonts/mutatorsans-variable/MutatorSansLightWide.ufo/glyphs/K_.glif new file mode 100644 index 00000000..6f8061f5 --- /dev/null +++ b/fixtures/fonts/mutatorsans-variable/MutatorSansLightWide.ufo/glyphs/K_.glif @@ -0,0 +1,28 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/fixtures/fonts/mutatorsans-variable/MutatorSansLightWide.ufo/glyphs/L_.glif b/fixtures/fonts/mutatorsans-variable/MutatorSansLightWide.ufo/glyphs/L_.glif new file mode 100644 index 00000000..b1bb16e5 --- /dev/null +++ b/fixtures/fonts/mutatorsans-variable/MutatorSansLightWide.ufo/glyphs/L_.glif @@ -0,0 +1,19 @@ + + + + + + + + + + + + + + + + + + + diff --git a/fixtures/fonts/mutatorsans-variable/MutatorSansLightWide.ufo/glyphs/M_.glif b/fixtures/fonts/mutatorsans-variable/MutatorSansLightWide.ufo/glyphs/M_.glif new file mode 100644 index 00000000..3403d3f0 --- /dev/null +++ b/fixtures/fonts/mutatorsans-variable/MutatorSansLightWide.ufo/glyphs/M_.glif @@ -0,0 +1,29 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/fixtures/fonts/mutatorsans-variable/MutatorSansLightWide.ufo/glyphs/N_.glif b/fixtures/fonts/mutatorsans-variable/MutatorSansLightWide.ufo/glyphs/N_.glif new file mode 100644 index 00000000..6a7073de --- /dev/null +++ b/fixtures/fonts/mutatorsans-variable/MutatorSansLightWide.ufo/glyphs/N_.glif @@ -0,0 +1,25 @@ + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/fixtures/fonts/mutatorsans-variable/MutatorSansLightWide.ufo/glyphs/O_.glif b/fixtures/fonts/mutatorsans-variable/MutatorSansLightWide.ufo/glyphs/O_.glif new file mode 100644 index 00000000..b5723838 --- /dev/null +++ b/fixtures/fonts/mutatorsans-variable/MutatorSansLightWide.ufo/glyphs/O_.glif @@ -0,0 +1,39 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/fixtures/fonts/mutatorsans-variable/MutatorSansLightWide.ufo/glyphs/P_.glif b/fixtures/fonts/mutatorsans-variable/MutatorSansLightWide.ufo/glyphs/P_.glif new file mode 100644 index 00000000..0625d631 --- /dev/null +++ b/fixtures/fonts/mutatorsans-variable/MutatorSansLightWide.ufo/glyphs/P_.glif @@ -0,0 +1,33 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/fixtures/fonts/mutatorsans-variable/MutatorSansLightWide.ufo/glyphs/Q_.glif b/fixtures/fonts/mutatorsans-variable/MutatorSansLightWide.ufo/glyphs/Q_.glif new file mode 100644 index 00000000..2a1da2a0 --- /dev/null +++ b/fixtures/fonts/mutatorsans-variable/MutatorSansLightWide.ufo/glyphs/Q_.glif @@ -0,0 +1,14 @@ + + + + + + + + + + + + + + diff --git a/fixtures/fonts/mutatorsans-variable/MutatorSansLightWide.ufo/glyphs/R_.glif b/fixtures/fonts/mutatorsans-variable/MutatorSansLightWide.ufo/glyphs/R_.glif new file mode 100644 index 00000000..9b34050a --- /dev/null +++ b/fixtures/fonts/mutatorsans-variable/MutatorSansLightWide.ufo/glyphs/R_.glif @@ -0,0 +1,42 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/fixtures/fonts/mutatorsans-variable/MutatorSansLightWide.ufo/glyphs/S_.closed.glif b/fixtures/fonts/mutatorsans-variable/MutatorSansLightWide.ufo/glyphs/S_.closed.glif new file mode 100644 index 00000000..08a88124 --- /dev/null +++ b/fixtures/fonts/mutatorsans-variable/MutatorSansLightWide.ufo/glyphs/S_.closed.glif @@ -0,0 +1,52 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/fixtures/fonts/mutatorsans-variable/MutatorSansLightWide.ufo/glyphs/S_.glif b/fixtures/fonts/mutatorsans-variable/MutatorSansLightWide.ufo/glyphs/S_.glif new file mode 100644 index 00000000..dda8c480 --- /dev/null +++ b/fixtures/fonts/mutatorsans-variable/MutatorSansLightWide.ufo/glyphs/S_.glif @@ -0,0 +1,65 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + com.typemytype.robofont.Image.Brightness + 0 + com.typemytype.robofont.Image.Contrast + 1 + com.typemytype.robofont.Image.Saturation + 1 + com.typemytype.robofont.Image.Sharpness + 0.4 + + + diff --git a/fixtures/fonts/mutatorsans-variable/MutatorSansLightWide.ufo/glyphs/T_.glif b/fixtures/fonts/mutatorsans-variable/MutatorSansLightWide.ufo/glyphs/T_.glif new file mode 100644 index 00000000..de53b29d --- /dev/null +++ b/fixtures/fonts/mutatorsans-variable/MutatorSansLightWide.ufo/glyphs/T_.glif @@ -0,0 +1,19 @@ + + + + + + + + + + + + + + + + + + + diff --git a/fixtures/fonts/mutatorsans-variable/MutatorSansLightWide.ufo/glyphs/U_.glif b/fixtures/fonts/mutatorsans-variable/MutatorSansLightWide.ufo/glyphs/U_.glif new file mode 100644 index 00000000..f17919fa --- /dev/null +++ b/fixtures/fonts/mutatorsans-variable/MutatorSansLightWide.ufo/glyphs/U_.glif @@ -0,0 +1,27 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/fixtures/fonts/mutatorsans-variable/MutatorSansLightWide.ufo/glyphs/V_.glif b/fixtures/fonts/mutatorsans-variable/MutatorSansLightWide.ufo/glyphs/V_.glif new file mode 100644 index 00000000..aa96bcef --- /dev/null +++ b/fixtures/fonts/mutatorsans-variable/MutatorSansLightWide.ufo/glyphs/V_.glif @@ -0,0 +1,25 @@ + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/fixtures/fonts/mutatorsans-variable/MutatorSansLightWide.ufo/glyphs/W_.glif b/fixtures/fonts/mutatorsans-variable/MutatorSansLightWide.ufo/glyphs/W_.glif new file mode 100644 index 00000000..c0e4302e --- /dev/null +++ b/fixtures/fonts/mutatorsans-variable/MutatorSansLightWide.ufo/glyphs/W_.glif @@ -0,0 +1,25 @@ + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/fixtures/fonts/mutatorsans-variable/MutatorSansLightWide.ufo/glyphs/X_.glif b/fixtures/fonts/mutatorsans-variable/MutatorSansLightWide.ufo/glyphs/X_.glif new file mode 100644 index 00000000..af8c9762 --- /dev/null +++ b/fixtures/fonts/mutatorsans-variable/MutatorSansLightWide.ufo/glyphs/X_.glif @@ -0,0 +1,25 @@ + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/fixtures/fonts/mutatorsans-variable/MutatorSansLightWide.ufo/glyphs/Y_.glif b/fixtures/fonts/mutatorsans-variable/MutatorSansLightWide.ufo/glyphs/Y_.glif new file mode 100644 index 00000000..c3aa70c1 --- /dev/null +++ b/fixtures/fonts/mutatorsans-variable/MutatorSansLightWide.ufo/glyphs/Y_.glif @@ -0,0 +1,25 @@ + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/fixtures/fonts/mutatorsans-variable/MutatorSansLightWide.ufo/glyphs/Z_.glif b/fixtures/fonts/mutatorsans-variable/MutatorSansLightWide.ufo/glyphs/Z_.glif new file mode 100644 index 00000000..9c01301f --- /dev/null +++ b/fixtures/fonts/mutatorsans-variable/MutatorSansLightWide.ufo/glyphs/Z_.glif @@ -0,0 +1,25 @@ + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/fixtures/fonts/mutatorsans-variable/MutatorSansLightWide.ufo/glyphs/_notdef.glif b/fixtures/fonts/mutatorsans-variable/MutatorSansLightWide.ufo/glyphs/_notdef.glif new file mode 100644 index 00000000..7bd7a779 --- /dev/null +++ b/fixtures/fonts/mutatorsans-variable/MutatorSansLightWide.ufo/glyphs/_notdef.glif @@ -0,0 +1,42 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + public.markColor + 0.6567,0.6903,1,1 + + + diff --git a/fixtures/fonts/mutatorsans-variable/MutatorSansLightWide.ufo/glyphs/acute.glif b/fixtures/fonts/mutatorsans-variable/MutatorSansLightWide.ufo/glyphs/acute.glif new file mode 100644 index 00000000..f1b10c6d --- /dev/null +++ b/fixtures/fonts/mutatorsans-variable/MutatorSansLightWide.ufo/glyphs/acute.glif @@ -0,0 +1,13 @@ + + + + + + + + + + + + + diff --git a/fixtures/fonts/mutatorsans-variable/MutatorSansLightWide.ufo/glyphs/arrowdown.glif b/fixtures/fonts/mutatorsans-variable/MutatorSansLightWide.ufo/glyphs/arrowdown.glif new file mode 100644 index 00000000..8392d98c --- /dev/null +++ b/fixtures/fonts/mutatorsans-variable/MutatorSansLightWide.ufo/glyphs/arrowdown.glif @@ -0,0 +1,18 @@ + + + + + + + + + + + + + + + + + + diff --git a/fixtures/fonts/mutatorsans-variable/MutatorSansLightWide.ufo/glyphs/arrowleft.glif b/fixtures/fonts/mutatorsans-variable/MutatorSansLightWide.ufo/glyphs/arrowleft.glif new file mode 100644 index 00000000..cdbd1cac --- /dev/null +++ b/fixtures/fonts/mutatorsans-variable/MutatorSansLightWide.ufo/glyphs/arrowleft.glif @@ -0,0 +1,18 @@ + + + + + + + + + + + + + + + + + + diff --git a/fixtures/fonts/mutatorsans-variable/MutatorSansLightWide.ufo/glyphs/arrowright.glif b/fixtures/fonts/mutatorsans-variable/MutatorSansLightWide.ufo/glyphs/arrowright.glif new file mode 100644 index 00000000..55b68fb9 --- /dev/null +++ b/fixtures/fonts/mutatorsans-variable/MutatorSansLightWide.ufo/glyphs/arrowright.glif @@ -0,0 +1,18 @@ + + + + + + + + + + + + + + + + + + diff --git a/fixtures/fonts/mutatorsans-variable/MutatorSansLightWide.ufo/glyphs/arrowup.glif b/fixtures/fonts/mutatorsans-variable/MutatorSansLightWide.ufo/glyphs/arrowup.glif new file mode 100644 index 00000000..1545bd7e --- /dev/null +++ b/fixtures/fonts/mutatorsans-variable/MutatorSansLightWide.ufo/glyphs/arrowup.glif @@ -0,0 +1,18 @@ + + + + + + + + + + + + + + + + + + diff --git a/fixtures/fonts/mutatorsans-variable/MutatorSansLightWide.ufo/glyphs/b.glif b/fixtures/fonts/mutatorsans-variable/MutatorSansLightWide.ufo/glyphs/b.glif new file mode 100644 index 00000000..16accedd --- /dev/null +++ b/fixtures/fonts/mutatorsans-variable/MutatorSansLightWide.ufo/glyphs/b.glif @@ -0,0 +1,7 @@ + + + + + + + diff --git a/fixtures/fonts/mutatorsans-variable/MutatorSansLightWide.ufo/glyphs/c.glif b/fixtures/fonts/mutatorsans-variable/MutatorSansLightWide.ufo/glyphs/c.glif new file mode 100644 index 00000000..0b4b3ccf --- /dev/null +++ b/fixtures/fonts/mutatorsans-variable/MutatorSansLightWide.ufo/glyphs/c.glif @@ -0,0 +1,7 @@ + + + + + + + diff --git a/fixtures/fonts/mutatorsans-variable/MutatorSansLightWide.ufo/glyphs/colon.glif b/fixtures/fonts/mutatorsans-variable/MutatorSansLightWide.ufo/glyphs/colon.glif new file mode 100644 index 00000000..e442b708 --- /dev/null +++ b/fixtures/fonts/mutatorsans-variable/MutatorSansLightWide.ufo/glyphs/colon.glif @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/fixtures/fonts/mutatorsans-variable/MutatorSansLightWide.ufo/glyphs/comma.glif b/fixtures/fonts/mutatorsans-variable/MutatorSansLightWide.ufo/glyphs/comma.glif new file mode 100644 index 00000000..b214a2eb --- /dev/null +++ b/fixtures/fonts/mutatorsans-variable/MutatorSansLightWide.ufo/glyphs/comma.glif @@ -0,0 +1,17 @@ + + + + + + + + + + + + + + + + + diff --git a/fixtures/fonts/mutatorsans-variable/MutatorSansLightWide.ufo/glyphs/contents.plist b/fixtures/fonts/mutatorsans-variable/MutatorSansLightWide.ufo/glyphs/contents.plist new file mode 100644 index 00000000..45273dee --- /dev/null +++ b/fixtures/fonts/mutatorsans-variable/MutatorSansLightWide.ufo/glyphs/contents.plist @@ -0,0 +1,104 @@ + + + + + .notdef + _notdef.glif + A + A_.glif + Aacute + A_acute.glif + Adieresis + A_dieresis.glif + B + B_.glif + C + C_.glif + D + D_.glif + E + E_.glif + F + F_.glif + G + G_.glif + H + H_.glif + I + I_.glif + I.narrow + I_.narrow.glif + IJ + I_J_.glif + J + J_.glif + J.narrow + J_.narrow.glif + K + K_.glif + L + L_.glif + M + M_.glif + N + N_.glif + O + O_.glif + P + P_.glif + Q + Q_.glif + R + R_.glif + S + S_.glif + S.closed + S_.closed.glif + T + T_.glif + U + U_.glif + V + V_.glif + W + W_.glif + X + X_.glif + Y + Y_.glif + Z + Z_.glif + acute + acute.glif + arrowdown + arrowdown.glif + arrowleft + arrowleft.glif + arrowright + arrowright.glif + arrowup + arrowup.glif + colon + colon.glif + comma + comma.glif + dieresis + dieresis.glif + dot + dot.glif + period + period.glif + quotedblbase + quotedblbase.glif + quotedblleft + quotedblleft.glif + quotedblright + quotedblright.glif + quotesinglbase + quotesinglbase.glif + semicolon + semicolon.glif + space + space.glif + + diff --git a/fixtures/fonts/mutatorsans-variable/MutatorSansLightWide.ufo/glyphs/d.glif b/fixtures/fonts/mutatorsans-variable/MutatorSansLightWide.ufo/glyphs/d.glif new file mode 100644 index 00000000..8fc09610 --- /dev/null +++ b/fixtures/fonts/mutatorsans-variable/MutatorSansLightWide.ufo/glyphs/d.glif @@ -0,0 +1,7 @@ + + + + + + + diff --git a/fixtures/fonts/mutatorsans-variable/MutatorSansLightWide.ufo/glyphs/dieresis.glif b/fixtures/fonts/mutatorsans-variable/MutatorSansLightWide.ufo/glyphs/dieresis.glif new file mode 100644 index 00000000..1eef4666 --- /dev/null +++ b/fixtures/fonts/mutatorsans-variable/MutatorSansLightWide.ufo/glyphs/dieresis.glif @@ -0,0 +1,15 @@ + + + + + + + + + + + public.markColor + 0.6567,0.6903,1,1 + + + diff --git a/fixtures/fonts/mutatorsans-variable/MutatorSansLightWide.ufo/glyphs/dot.glif b/fixtures/fonts/mutatorsans-variable/MutatorSansLightWide.ufo/glyphs/dot.glif new file mode 100644 index 00000000..8f14d475 --- /dev/null +++ b/fixtures/fonts/mutatorsans-variable/MutatorSansLightWide.ufo/glyphs/dot.glif @@ -0,0 +1,13 @@ + + + + + + + + + + + + + diff --git a/fixtures/fonts/mutatorsans-variable/MutatorSansLightWide.ufo/glyphs/layerinfo.plist b/fixtures/fonts/mutatorsans-variable/MutatorSansLightWide.ufo/glyphs/layerinfo.plist new file mode 100644 index 00000000..aeeb1b2a --- /dev/null +++ b/fixtures/fonts/mutatorsans-variable/MutatorSansLightWide.ufo/glyphs/layerinfo.plist @@ -0,0 +1,13 @@ + + + + + color + 1,0.75,0,0.7 + lib + + com.typemytype.robofont.segmentType + curve + + + diff --git a/fixtures/fonts/mutatorsans-variable/MutatorSansLightWide.ufo/glyphs/period.glif b/fixtures/fonts/mutatorsans-variable/MutatorSansLightWide.ufo/glyphs/period.glif new file mode 100644 index 00000000..3a362b47 --- /dev/null +++ b/fixtures/fonts/mutatorsans-variable/MutatorSansLightWide.ufo/glyphs/period.glif @@ -0,0 +1,13 @@ + + + + + + + + + + + + + diff --git a/fixtures/fonts/mutatorsans-variable/MutatorSansLightWide.ufo/glyphs/quotedblbase.glif b/fixtures/fonts/mutatorsans-variable/MutatorSansLightWide.ufo/glyphs/quotedblbase.glif new file mode 100644 index 00000000..fbfc8536 --- /dev/null +++ b/fixtures/fonts/mutatorsans-variable/MutatorSansLightWide.ufo/glyphs/quotedblbase.glif @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/fixtures/fonts/mutatorsans-variable/MutatorSansLightWide.ufo/glyphs/quotedblleft.glif b/fixtures/fonts/mutatorsans-variable/MutatorSansLightWide.ufo/glyphs/quotedblleft.glif new file mode 100644 index 00000000..f34371e4 --- /dev/null +++ b/fixtures/fonts/mutatorsans-variable/MutatorSansLightWide.ufo/glyphs/quotedblleft.glif @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/fixtures/fonts/mutatorsans-variable/MutatorSansLightWide.ufo/glyphs/quotedblright.glif b/fixtures/fonts/mutatorsans-variable/MutatorSansLightWide.ufo/glyphs/quotedblright.glif new file mode 100644 index 00000000..53e5d26a --- /dev/null +++ b/fixtures/fonts/mutatorsans-variable/MutatorSansLightWide.ufo/glyphs/quotedblright.glif @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/fixtures/fonts/mutatorsans-variable/MutatorSansLightWide.ufo/glyphs/quotesinglbase.glif b/fixtures/fonts/mutatorsans-variable/MutatorSansLightWide.ufo/glyphs/quotesinglbase.glif new file mode 100644 index 00000000..4ff1ffbb --- /dev/null +++ b/fixtures/fonts/mutatorsans-variable/MutatorSansLightWide.ufo/glyphs/quotesinglbase.glif @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/fixtures/fonts/mutatorsans-variable/MutatorSansLightWide.ufo/glyphs/semicolon.glif b/fixtures/fonts/mutatorsans-variable/MutatorSansLightWide.ufo/glyphs/semicolon.glif new file mode 100644 index 00000000..995849fd --- /dev/null +++ b/fixtures/fonts/mutatorsans-variable/MutatorSansLightWide.ufo/glyphs/semicolon.glif @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/fixtures/fonts/mutatorsans-variable/MutatorSansLightWide.ufo/glyphs/space.glif b/fixtures/fonts/mutatorsans-variable/MutatorSansLightWide.ufo/glyphs/space.glif new file mode 100644 index 00000000..80c661f7 --- /dev/null +++ b/fixtures/fonts/mutatorsans-variable/MutatorSansLightWide.ufo/glyphs/space.glif @@ -0,0 +1,7 @@ + + + + + + + diff --git a/fixtures/fonts/mutatorsans-variable/MutatorSansLightWide.ufo/groups.plist b/fixtures/fonts/mutatorsans-variable/MutatorSansLightWide.ufo/groups.plist new file mode 100644 index 00000000..7dc9fccd --- /dev/null +++ b/fixtures/fonts/mutatorsans-variable/MutatorSansLightWide.ufo/groups.plist @@ -0,0 +1,20 @@ + + + + + public.kern1.@MMK_L_A + + A + + public.kern2.@MMK_R_A + + A + + testGroup + + E + F + H + + + diff --git a/fixtures/fonts/mutatorsans-variable/MutatorSansLightWide.ufo/kerning.plist b/fixtures/fonts/mutatorsans-variable/MutatorSansLightWide.ufo/kerning.plist new file mode 100644 index 00000000..5fda98fd --- /dev/null +++ b/fixtures/fonts/mutatorsans-variable/MutatorSansLightWide.ufo/kerning.plist @@ -0,0 +1,210 @@ + + + + + B + + H + -40 + J + -85 + O + -10 + S + -25 + T + -85 + U + -35 + V + -85 + public.kern2.@MMK_R_A + -25 + + C + + J + -75 + T + -40 + V + -65 + public.kern2.@MMK_R_A + -40 + + E + + J + -80 + T + -10 + + F + + H + -35 + J + -245 + O + -50 + S + -70 + U + -10 + public.kern2.@MMK_R_A + -125 + + G + + J + -60 + O + -15 + S + -15 + T + -105 + U + -20 + V + -70 + public.kern2.@MMK_R_A + -40 + + H + + J + -40 + S + -30 + + J + + J + -135 + O + -10 + public.kern2.@MMK_R_A + -70 + + L + + J + -25 + O + -95 + T + -305 + U + -85 + V + -185 + + O + + J + -120 + S + -45 + T + -90 + V + -80 + public.kern2.@MMK_R_A + -30 + + P + + J + -200 + T + -20 + public.kern2.@MMK_R_A + -95 + + R + + H + -45 + J + -155 + O + -55 + S + -70 + T + -80 + U + -60 + V + -95 + public.kern2.@MMK_R_A + -80 + + S + + H + -5 + J + -115 + O + -40 + S + -45 + T + -50 + U + -10 + V + -20 + public.kern2.@MMK_R_A + -45 + + T + + H + -15 + J + -315 + O + -90 + S + -25 + public.kern2.@MMK_R_A + -215 + + U + + J + -140 + public.kern2.@MMK_R_A + -75 + + V + + H + -20 + J + -265 + O + -55 + S + -50 + public.kern2.@MMK_R_A + -210 + + public.kern1.@MMK_L_A + + J + -35 + O + -55 + T + -190 + U + -95 + V + -180 + + + diff --git a/fixtures/fonts/mutatorsans-variable/MutatorSansLightWide.ufo/layercontents.plist b/fixtures/fonts/mutatorsans-variable/MutatorSansLightWide.ufo/layercontents.plist new file mode 100644 index 00000000..e9a336b2 --- /dev/null +++ b/fixtures/fonts/mutatorsans-variable/MutatorSansLightWide.ufo/layercontents.plist @@ -0,0 +1,14 @@ + + + + + + foreground + glyphs + + + background + glyphs.background + + + diff --git a/fixtures/fonts/mutatorsans-variable/MutatorSansLightWide.ufo/lib.plist b/fixtures/fonts/mutatorsans-variable/MutatorSansLightWide.ufo/lib.plist new file mode 100644 index 00000000..73160063 --- /dev/null +++ b/fixtures/fonts/mutatorsans-variable/MutatorSansLightWide.ufo/lib.plist @@ -0,0 +1,623 @@ + + + + + com.defcon.sortDescriptor + + + allowPseudoUnicode + + type + cannedDesign + + + com.typemytype.robofont.background.layerStrokeColor + + 1.0 + 0.75 + 0.0 + 0.7 + + com.typemytype.robofont.compileSettings.autohint + + com.typemytype.robofont.compileSettings.checkOutlines + + com.typemytype.robofont.compileSettings.createDummyDSIG + + com.typemytype.robofont.compileSettings.decompose + + com.typemytype.robofont.compileSettings.generateFormat + 0 + com.typemytype.robofont.compileSettings.releaseMode + + com.typemytype.robofont.foreground.layerStrokeColor + + 0.5 + 0.0 + 0.5 + 0.7 + + com.typemytype.robofont.italicSlantOffset + 0 + com.typemytype.robofont.segmentType + curve + com.typemytype.robofont.shouldAddPointsInSplineConversion + 1 + com.typesupply.MetricsMachine4.groupColors + + @MMK_L_A + + 1.0 + 0.0 + 0.0 + 0.25 + + @MMK_L_C + + 1.0 + 0.5 + 0.0 + 0.25 + + @MMK_L_E + + 1.0 + 1.0 + 0.0 + 0.25 + + @MMK_L_I + + 0.0 + 1.0 + 0.0 + 0.25 + + @MMK_L_N + + 0.0 + 1.0 + 1.0 + 0.25 + + @MMK_L_O + + 0.0 + 0.5 + 1.0 + 0.25 + + @MMK_L_S + + 0.0 + 0.0 + 1.0 + 0.25 + + @MMK_L_U + + 0.5 + 0.0 + 1.0 + 0.25 + + @MMK_L_Y + + 1.0 + 0.0 + 1.0 + 0.25 + + @MMK_L_Z + + 1.0 + 0.0 + 0.5 + 0.25 + + @MMK_L_a + + 1.0 + 0.0 + 0.0 + 0.25 + + @MMK_L_c + + 1.0 + 0.5 + 0.0 + 0.25 + + @MMK_L_e + + 1.0 + 1.0 + 0.0 + 0.25 + + @MMK_L_i + + 0.0 + 1.0 + 0.0 + 0.25 + + @MMK_L_n + + 0.0 + 1.0 + 1.0 + 0.25 + + @MMK_L_o + + 0.0 + 0.5 + 1.0 + 0.25 + + @MMK_L_s + + 0.0 + 0.0 + 1.0 + 0.25 + + @MMK_L_u + + 0.5 + 0.0 + 1.0 + 0.25 + + @MMK_L_y + + 1.0 + 0.0 + 1.0 + 0.25 + + @MMK_L_z + + 1.0 + 0.0 + 0.5 + 0.25 + + @MMK_R_A + + 1.0 + 0.0 + 0.0 + 0.25 + + @MMK_R_C + + 1.0 + 0.5 + 0.0 + 0.25 + + @MMK_R_E + + 1.0 + 1.0 + 0.0 + 0.25 + + @MMK_R_I + + 0.0 + 1.0 + 0.0 + 0.25 + + @MMK_R_N + + 0.0 + 1.0 + 1.0 + 0.25 + + @MMK_R_O + + 0.0 + 0.5 + 1.0 + 0.25 + + @MMK_R_S + + 0.0 + 0.0 + 1.0 + 0.25 + + @MMK_R_U + + 0.5 + 0.0 + 1.0 + 0.25 + + @MMK_R_Y + + 1.0 + 0.0 + 1.0 + 0.25 + + @MMK_R_Z + + 1.0 + 0.0 + 0.5 + 0.25 + + @MMK_R_a + + 1.0 + 0.0 + 0.0 + 0.25 + + @MMK_R_c + + 1.0 + 0.5 + 0.0 + 0.25 + + @MMK_R_e + + 1.0 + 1.0 + 0.0 + 0.25 + + @MMK_R_i + + 0.0 + 1.0 + 0.0 + 0.25 + + @MMK_R_n + + 0.0 + 1.0 + 1.0 + 0.25 + + @MMK_R_o + + 0.0 + 0.5 + 1.0 + 0.25 + + @MMK_R_s + + 0.0 + 0.0 + 1.0 + 0.25 + + @MMK_R_u + + 0.5 + 0.0 + 1.0 + 0.25 + + @MMK_R_y + + 1.0 + 0.0 + 1.0 + 0.25 + + @MMK_R_z + + 1.0 + 0.0 + 0.5 + 0.25 + + + com.typesupply.defcon.sortDescriptor + + + ascending + + space + A + Agrave + Aacute + Acircumflex + Atilde + Adieresis + Aring + B + C + Ccedilla + D + E + Egrave + Eacute + Ecircumflex + Edieresis + F + G + H + I + Igrave + Iacute + Icircumflex + Idieresis + J + K + L + M + N + Ntilde + O + Ograve + Oacute + Ocircumflex + Otilde + Odieresis + P + Q + R + S + Scaron + T + U + Ugrave + Uacute + Ucircumflex + Udieresis + V + W + X + Y + Yacute + Ydieresis + Z + Zcaron + AE + Eth + Oslash + Thorn + Lslash + OE + a + agrave + aacute + acircumflex + atilde + adieresis + aring + b + c + ccedilla + d + e + egrave + eacute + ecircumflex + edieresis + f + g + h + i + igrave + iacute + icircumflex + idieresis + j + k + l + m + n + ntilde + o + ograve + oacute + ocircumflex + otilde + odieresis + p + q + r + s + scaron + t + u + ugrave + uacute + ucircumflex + udieresis + v + w + x + y + yacute + ydieresis + z + zcaron + ordfeminine + ordmasculine + germandbls + ae + eth + oslash + thorn + dotlessi + lslash + oe + zero + one + two + three + four + five + six + seven + eight + nine + onesuperior + twosuperior + threesuperior + onequarter + onehalf + threequarters + underscore + hyphen + endash + emdash + parenleft + parenright + bracketleft + bracketright + braceleft + braceright + numbersign + percent + perthousand + quotesingle + quotedbl + quoteleft + quoteright + quotedblleft + quotedblright + quotesinglbase + quotedblbase + guilsinglleft + guilsinglright + guillemotleft + guillemotright + asterisk + dagger + daggerdbl + period + comma + colon + semicolon + ellipsis + exclam + exclamdown + question + questiondown + slash + backslash + fraction + bar + brokenbar + at + ampersand + section + paragraph + periodcentered + bullet + plus + minus + plusminus + divide + multiply + equal + less + greater + logicalnot + mu + dollar + cent + sterling + currency + yen + Euro + florin + asciicircum + asciitilde + acute + grave + hungarumlaut + circumflex + caron + breve + tilde + macron + dieresis + dotaccent + ring + cedilla + ogonek + copyright + registered + trademark + degree + fi + fl + .notdef + a_b_c + + type + glyphList + + + public.glyphOrder + + space + A + Aacute + Adieresis + B + C + D + E + F + G + H + I + J + K + L + M + N + O + P + Q + R + S + T + U + V + W + X + Y + Z + quotedblleft + quotedblright + quotesinglbase + quotedblbase + period + comma + colon + semicolon + arrowleft + arrowup + arrowright + arrowdown + dot + acute + dieresis + IJ + I.narrow + J.narrow + S.closed + .notdef + + + diff --git a/fixtures/fonts/mutatorsans-variable/MutatorSansLightWide.ufo/metainfo.plist b/fixtures/fonts/mutatorsans-variable/MutatorSansLightWide.ufo/metainfo.plist new file mode 100644 index 00000000..7b8b34ac --- /dev/null +++ b/fixtures/fonts/mutatorsans-variable/MutatorSansLightWide.ufo/metainfo.plist @@ -0,0 +1,10 @@ + + + + + creator + com.github.fonttools.ufoLib + formatVersion + 3 + + diff --git a/packages/types/__fixtures__/variation_parity.json b/packages/types/__fixtures__/variation_parity.json new file mode 100644 index 00000000..a7761f3f --- /dev/null +++ b/packages/types/__fixtures__/variation_parity.json @@ -0,0 +1,438 @@ +{ + "glyphName": "A", + "designspaceTarget": { + "wdth": 500.0, + "wght": 500.0 + }, + "normalisedLocation": { + "wdth": 0.5, + "wght": 0.5 + }, + "data": { + "regions": [ + [ + { + "axisTag": "wdth", + "lower": 0.0, + "peak": 0.0, + "upper": 0.0 + }, + { + "axisTag": "wght", + "lower": 0.0, + "peak": 0.0, + "upper": 0.0 + } + ], + [ + { + "axisTag": "wdth", + "lower": 0.0, + "peak": 1.0, + "upper": 1.0 + }, + { + "axisTag": "wght", + "lower": 0.0, + "peak": 0.0, + "upper": 0.0 + } + ], + [ + { + "axisTag": "wdth", + "lower": 0.0, + "peak": 0.0, + "upper": 0.0 + }, + { + "axisTag": "wght", + "lower": 0.0, + "peak": 1.0, + "upper": 1.0 + } + ], + [ + { + "axisTag": "wdth", + "lower": 0.0, + "peak": 1.0, + "upper": 1.0 + }, + { + "axisTag": "wght", + "lower": 0.0, + "peak": 1.0, + "upper": 1.0 + } + ] + ], + "deltas": [ + [ + 396.0, + 20.0, + 0.0, + 60.0, + 0.0, + 200.0, + 700.0, + 165.0, + 700.0, + 75.0, + 164.0, + 325.0, + 164.0, + 325.0, + 200.0, + 75.0, + 200.0, + 332.0, + 0.0, + 376.0, + 0.0, + 231.0, + 700.0, + 192.0, + 700.0, + 175.0, + 661.0, + 222.0, + 661.0, + 222.0, + 700.0, + 175.0, + 700.0 + ], + [ + 794.0, + 30.0, + 0.0, + 37.0, + 0.0, + 412.0, + 0.0, + 405.0, + 0.0, + 170.0, + 60.0, + 620.0, + 60.0, + 620.0, + 54.0, + 170.0, + 54.0, + 755.0, + 0.0, + 764.0, + 0.0, + 389.0, + 0.0, + 380.0, + 0.0, + 395.0, + 3.0, + 398.0, + 3.0, + 398.0, + 0.0, + 395.0, + 0.0 + ], + [ + 344.0, + -30.0, + 0.0, + 190.0, + 0.0, + 134.0, + 100.0, + -61.0, + 100.0, + 35.0, + -44.0, + 255.0, + -44.0, + 255.0, + 130.0, + 35.0, + 130.0, + 58.0, + 0.0, + 354.0, + 0.0, + 383.0, + 100.0, + 102.0, + 100.0, + 29.0, + -121.0, + 252.0, + -121.0, + 252.0, + 100.0, + 29.0, + 100.0 + ], + [ + -244.0, + 0.0, + 0.0, + 63.0, + 0.0, + -106.0, + 0.0, + -149.0, + 0.0, + -70.0, + -60.0, + -260.0, + -60.0, + -260.0, + -44.0, + -70.0, + -44.0, + -345.0, + 0.0, + -224.0, + 0.0, + -73.0, + 0.0, + -194.0, + 0.0, + -189.0, + -3.0, + -42.0, + -3.0, + -42.0, + 0.0, + -189.0, + 0.0 + ] + ] + }, + "expected": [ + 904.0, + 20.0, + 0.0, + 189.25, + 0.0, + 446.5, + 750.0, + 299.75, + 750.0, + 160.0, + 157.0, + 697.5, + 157.0, + 697.5, + 281.0, + 160.0, + 281.0, + 652.25, + 0.0, + 879.0, + 0.0, + 598.75, + 750.0, + 384.5, + 750.0, + 339.75, + 601.25, + 536.5, + 601.25, + 536.5, + 750.0, + 339.75, + 750.0 + ], + "masters": [ + { + "sourceName": "LightCondensed", + "isDefaultSource": true, + "designspaceLocation": { + "wdth": 0.0, + "wght": 0.0 + }, + "normalisedLocation": { + "wdth": 0.0, + "wght": 0.0 + }, + "expected": [ + 396.0, + 20.0, + 0.0, + 60.0, + 0.0, + 200.0, + 700.0, + 165.0, + 700.0, + 75.0, + 164.0, + 325.0, + 164.0, + 325.0, + 200.0, + 75.0, + 200.0, + 332.0, + 0.0, + 376.0, + 0.0, + 231.0, + 700.0, + 192.0, + 700.0, + 175.0, + 661.0, + 222.0, + 661.0, + 222.0, + 700.0, + 175.0, + 700.0 + ] + }, + { + "sourceName": "BoldCondensed", + "isDefaultSource": false, + "designspaceLocation": { + "wdth": 0.0, + "wght": 1000.0 + }, + "normalisedLocation": { + "wdth": 0.0, + "wght": 1.0 + }, + "expected": [ + 740.0, + -10.0, + 0.0, + 250.0, + 0.0, + 334.0, + 800.0, + 104.0, + 800.0, + 110.0, + 120.0, + 580.0, + 120.0, + 580.0, + 330.0, + 110.0, + 330.0, + 390.0, + 0.0, + 730.0, + 0.0, + 614.0, + 800.0, + 294.0, + 800.0, + 204.0, + 540.0, + 474.0, + 540.0, + 474.0, + 800.0, + 204.0, + 800.0 + ] + }, + { + "sourceName": "LightWide", + "isDefaultSource": false, + "designspaceLocation": { + "wdth": 1000.0, + "wght": 0.0 + }, + "normalisedLocation": { + "wdth": 1.0, + "wght": 0.0 + }, + "expected": [ + 1190.0, + 50.0, + 0.0, + 97.0, + 0.0, + 612.0, + 700.0, + 570.0, + 700.0, + 245.0, + 224.0, + 945.0, + 224.0, + 945.0, + 254.0, + 245.0, + 254.0, + 1087.0, + 0.0, + 1140.0, + 0.0, + 620.0, + 700.0, + 572.0, + 700.0, + 570.0, + 664.0, + 620.0, + 664.0, + 620.0, + 700.0, + 570.0, + 700.0 + ] + }, + { + "sourceName": "BoldWide", + "isDefaultSource": false, + "designspaceLocation": { + "wdth": 1000.0, + "wght": 1000.0 + }, + "normalisedLocation": { + "wdth": 1.0, + "wght": 1.0 + }, + "expected": [ + 1290.0, + 20.0, + 0.0, + 350.0, + 0.0, + 640.0, + 800.0, + 360.0, + 800.0, + 210.0, + 120.0, + 940.0, + 120.0, + 940.0, + 340.0, + 210.0, + 340.0, + 800.0, + 0.0, + 1270.0, + 0.0, + 930.0, + 800.0, + 480.0, + 800.0, + 410.0, + 540.0, + 830.0, + 540.0, + 830.0, + 800.0, + 410.0, + 800.0 + ] + } + ] +} diff --git a/packages/types/src/font.ts b/packages/types/src/font.ts index 29735ec6..b826d0ed 100644 --- a/packages/types/src/font.ts +++ b/packages/types/src/font.ts @@ -11,11 +11,20 @@ export type { RenderPointSnapshot, RenderContourSnapshot, GlyphSnapshot, + GlyphGeometry, + MasterSnapshot, + InterpolationResult, + SourceError, + AxisTent, + GlyphVariationData, CommandResult, RuleId, MatchedRule, FontMetrics, FontMetadata, + Axis, + Location, + Source, } from "./generated"; // Domain types (for Editor API) diff --git a/packages/types/src/generated/Axis.ts b/packages/types/src/generated/Axis.ts new file mode 100644 index 00000000..185f21dc --- /dev/null +++ b/packages/types/src/generated/Axis.ts @@ -0,0 +1,3 @@ +// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. + +export type Axis = { tag: string, name: string, minimum: number, default: number, maximum: number, hidden: boolean, }; diff --git a/packages/types/src/generated/AxisTent.ts b/packages/types/src/generated/AxisTent.ts new file mode 100644 index 00000000..ca476146 --- /dev/null +++ b/packages/types/src/generated/AxisTent.ts @@ -0,0 +1,3 @@ +// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. + +export type AxisTent = { axisTag: string, lower: number, peak: number, upper: number, }; diff --git a/packages/types/src/generated/GlyphGeometry.ts b/packages/types/src/generated/GlyphGeometry.ts new file mode 100644 index 00000000..2a3f13dd --- /dev/null +++ b/packages/types/src/generated/GlyphGeometry.ts @@ -0,0 +1,5 @@ +// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. +import type { AnchorSnapshot } from "./AnchorSnapshot"; +import type { ContourSnapshot } from "./ContourSnapshot"; + +export type GlyphGeometry = { xAdvance: number, contours: Array, anchors: Array, }; diff --git a/packages/types/src/generated/GlyphVariationData.ts b/packages/types/src/generated/GlyphVariationData.ts new file mode 100644 index 00000000..da446126 --- /dev/null +++ b/packages/types/src/generated/GlyphVariationData.ts @@ -0,0 +1,13 @@ +// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. +import type { AxisTent } from "./AxisTent"; + +export type GlyphVariationData = { +/** + * One entry per region. Inner = tents on the axes the region depends on. + */ +regions: Array>, +/** + * Same length as `regions`. Each entry = flat values matching `flatten()` order: + * [xAdvance, p0.x, p0.y, ..., a0.x, a0.y, ...]. + */ +deltas: Array>, }; diff --git a/packages/types/src/generated/InterpolationResult.ts b/packages/types/src/generated/InterpolationResult.ts new file mode 100644 index 00000000..1e3e8edc --- /dev/null +++ b/packages/types/src/generated/InterpolationResult.ts @@ -0,0 +1,5 @@ +// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. +import type { GlyphGeometry } from "./GlyphGeometry"; +import type { SourceError } from "./SourceError"; + +export type InterpolationResult = { geometry: GlyphGeometry, errors: Array, }; diff --git a/packages/types/src/generated/Location.ts b/packages/types/src/generated/Location.ts new file mode 100644 index 00000000..dbbf8be7 --- /dev/null +++ b/packages/types/src/generated/Location.ts @@ -0,0 +1,3 @@ +// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. + +export type Location = { values: { [key in string]?: number }, }; diff --git a/packages/types/src/generated/MasterSnapshot.ts b/packages/types/src/generated/MasterSnapshot.ts new file mode 100644 index 00000000..c80e0bf8 --- /dev/null +++ b/packages/types/src/generated/MasterSnapshot.ts @@ -0,0 +1,5 @@ +// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. +import type { GlyphGeometry } from "./GlyphGeometry"; +import type { Location } from "./Location"; + +export type MasterSnapshot = { sourceId: string, sourceName: string, isDefaultSource: boolean, location: Location, geometry: GlyphGeometry, }; diff --git a/packages/types/src/generated/Source.ts b/packages/types/src/generated/Source.ts new file mode 100644 index 00000000..33e14357 --- /dev/null +++ b/packages/types/src/generated/Source.ts @@ -0,0 +1,4 @@ +// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. +import type { Location } from "./Location"; + +export type Source = { id: string, name: string, location: Location, layerId: string, filename: string | null, }; diff --git a/packages/types/src/generated/SourceError.ts b/packages/types/src/generated/SourceError.ts new file mode 100644 index 00000000..0fa35723 --- /dev/null +++ b/packages/types/src/generated/SourceError.ts @@ -0,0 +1,3 @@ +// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. + +export type SourceError = { sourceIndex: number, sourceName: string, message: string, }; diff --git a/packages/types/src/generated/index.ts b/packages/types/src/generated/index.ts index 80334416..286f609f 100644 --- a/packages/types/src/generated/index.ts +++ b/packages/types/src/generated/index.ts @@ -9,9 +9,18 @@ export type { AnchorSnapshot } from "./AnchorSnapshot"; export type { RenderPointSnapshot } from "./RenderPointSnapshot"; export type { RenderContourSnapshot } from "./RenderContourSnapshot"; export type { GlyphSnapshot } from "./GlyphSnapshot"; +export type { GlyphGeometry } from "./GlyphGeometry"; +export type { MasterSnapshot } from "./MasterSnapshot"; +export type { InterpolationResult } from "./InterpolationResult"; +export type { SourceError } from "./SourceError"; +export type { AxisTent } from "./AxisTent"; +export type { GlyphVariationData } from "./GlyphVariationData"; export type { CommandResult } from "./CommandResult"; export type { RuleId } from "./RuleId"; export type { MatchedRule } from "./MatchedRule"; export type { FontMetrics } from "./FontMetrics"; export type { FontMetadata } from "./FontMetadata"; export type { DecomposedTransform } from "./DecomposedTransform"; +export type { Axis } from "./Axis"; +export type { Location } from "./Location"; +export type { Source } from "./Source"; diff --git a/packages/types/src/index.ts b/packages/types/src/index.ts index 4ec58d92..a09fa65a 100644 --- a/packages/types/src/index.ts +++ b/packages/types/src/index.ts @@ -31,12 +31,21 @@ export type { RenderPointSnapshot, RenderContourSnapshot, GlyphSnapshot, + GlyphGeometry, + MasterSnapshot, + InterpolationResult, + SourceError, + AxisTent, + GlyphVariationData, CommandResult, RuleId, MatchedRule, FontMetadata, FontMetrics, DecomposedTransform, + Axis, + Location, + Source, } from "./font"; // Domain types (for Editor API) diff --git a/scripts/oxlint/shift-plugin.mjs b/scripts/oxlint/shift-plugin.mjs index e2b2019f..d132a4ec 100644 --- a/scripts/oxlint/shift-plugin.mjs +++ b/scripts/oxlint/shift-plugin.mjs @@ -23,6 +23,7 @@ const CONTOURS_ALLOWED = [ "Editor.ts", // coordinator-level structural traversal "clipboard/", // ClipboardContent is not a Glyph, different type "ContourDoubleClick.ts", // finds contour by segment match + "interpolation/", // interpolation produces snapshots from raw contour data ]; function checkParam(context, node) { @@ -60,6 +61,7 @@ const SNAPSHOT_ALLOWED = [ "behaviors/", // tool behaviors capture snapshots for undo via drafts "types/engine.ts", // engine response types "lib/model/", // reactive model uses snapshots for sync + "interpolation/", // interpolation produces snapshots by blending masters ]; function isAllowedFile(filename, allowList) { diff --git a/scripts/patch-generated-types.ts b/scripts/patch-generated-types.ts index a2635efc..2ef4ae00 100644 --- a/scripts/patch-generated-types.ts +++ b/scripts/patch-generated-types.ts @@ -25,6 +25,19 @@ const FILE_IMPORTS: Record = { "CommandResult.ts": ["PointId"], }; +/** Match what pre-commit's trailing-whitespace + end-of-file-fixer do, so the + * hooks don't re-modify these files on every commit attempt. ts-rs emits + * trailing whitespace and no terminating newline. */ +function normalizeWhitespace(content: string): string { + return ( + content + .split("\n") + .map((line) => line.replace(/[ \t]+$/, "")) + .join("\n") + .replace(/\n*$/, "") + "\n" + ); +} + function patchFile(filename: string, imports: string[]): boolean { const filePath = path.join(GENERATED_DIR, filename); @@ -36,23 +49,30 @@ function patchFile(filename: string, imports: string[]): boolean { let content = fs.readFileSync(filePath, "utf8"); const importStatement = `import type { ${imports.join(", ")} } from "../ids";\n`; + const tsrsComment = + "// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually."; - if (content.includes('from "../ids"')) { - console.log(`✓ ${filename} already patched`); - return true; + const alreadyHasImport = content.includes('from "../ids"'); + + if (!alreadyHasImport) { + if (content.startsWith(tsrsComment)) { + content = tsrsComment + "\n" + importStatement + content.slice(tsrsComment.length); + } else { + content = importStatement + content; + } } - const tsrsComment = - "// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually."; + content = normalizeWhitespace(content); - if (content.startsWith(tsrsComment)) { - content = tsrsComment + "\n" + importStatement + content.slice(tsrsComment.length); - } else { - content = importStatement + content; + // Avoid touching disk if nothing actually changed — keeps git unaware. + const existing = fs.readFileSync(filePath, "utf8"); + if (existing === content) { + console.info(`✓ ${filename} already patched`); + return true; } fs.writeFileSync(filePath, content); - console.log(`✅ Patched ${filename} with imports: ${imports.join(", ")}`); + console.info(`✅ Patched ${filename} with imports: ${imports.join(", ")}`); return true; } @@ -68,7 +88,7 @@ function patchNapiDts(): boolean { const importLine = 'import type { ContourId, PointId, AnchorId } from "@shift/types";'; if (content.includes(importLine)) { - console.log("✓ shift-node/index.d.ts already patched"); + console.info("✓ shift-node/index.d.ts already patched"); return true; } @@ -80,12 +100,31 @@ function patchNapiDts(): boolean { } fs.writeFileSync(napiDtsPath, content); - console.log("✅ Patched shift-node/index.d.ts with branded ID imports"); + console.info("✅ Patched shift-node/index.d.ts with branded ID imports"); return true; } +/** Normalize whitespace on every generated file (whether it needs an ID + * import or not). ts-rs emits trailing whitespace + no terminating newline + * — left untouched, pre-commit's trailing-whitespace + end-of-file-fixer + * hooks would re-flag every commit. */ +function normalizeAllGenerated(): void { + if (!fs.existsSync(GENERATED_DIR)) return; + for (const filename of fs.readdirSync(GENERATED_DIR)) { + if (!filename.endsWith(".ts")) continue; + if (filename in FILE_IMPORTS) continue; // patchFile already normalised + const filePath = path.join(GENERATED_DIR, filename); + const original = fs.readFileSync(filePath, "utf8"); + const normalized = normalizeWhitespace(original); + if (original !== normalized) { + fs.writeFileSync(filePath, normalized); + console.info(`✅ Normalised whitespace in ${filename}`); + } + } +} + function main(): void { - console.log("🔧 Patching generated types with branded ID imports...\n"); + console.info("🔧 Patching generated types with branded ID imports...\n"); let success = true; @@ -95,14 +134,16 @@ function main(): void { } } + normalizeAllGenerated(); + if (!patchNapiDts()) { success = false; } - console.log(""); + console.info(""); if (success) { - console.log("✅ All generated types patched successfully!"); + console.info("✅ All generated types patched successfully!"); } else { console.error("❌ Some files could not be patched"); process.exit(1);