├── .nvmrc
├── .taurignore
├── packages
└── shared
│ ├── README.md
│ ├── src
│ ├── types
│ │ ├── PointType.ts
│ │ ├── EntityId.ts
│ │ ├── FontLoadedEvent.ts
│ │ ├── FontCompiledEvent.ts
│ │ ├── FontMetadata.ts
│ │ ├── Metrics.ts
│ │ ├── PointsAddedEvent.ts
│ │ ├── PointsMovedEvent.ts
│ │ ├── IContour.ts
│ │ ├── Glyph.ts
│ │ ├── IContourPoint.ts
│ │ ├── MovedPoint.ts
│ │ ├── Font.ts
│ │ └── PathCommand.ts
│ └── index.ts
│ ├── tsconfig.json
│ ├── scripts
│ └── exports-ts-rs.js
│ └── package.json
├── crates
├── shift-unicode
│ ├── src
│ │ ├── unicode.rs
│ │ └── lib.rs
│ ├── build.rs
│ └── Cargo.toml
├── shift-events
│ ├── src
│ │ ├── lib.rs
│ │ └── events.rs
│ └── Cargo.toml
├── shift-editor
│ ├── src
│ │ ├── lib.rs
│ │ └── editor.rs
│ └── Cargo.toml
├── shift-tauri
│ ├── build.rs
│ ├── icons
│ │ ├── 32x32.png
│ │ ├── icon.icns
│ │ ├── icon.ico
│ │ ├── icon.png
│ │ ├── 128x128.png
│ │ ├── 128x128@2x.png
│ │ ├── StoreLogo.png
│ │ ├── Square30x30Logo.png
│ │ ├── Square44x44Logo.png
│ │ ├── Square71x71Logo.png
│ │ ├── Square89x89Logo.png
│ │ ├── Square107x107Logo.png
│ │ ├── Square142x142Logo.png
│ │ ├── Square150x150Logo.png
│ │ ├── Square284x284Logo.png
│ │ ├── Square310x310Logo.png
│ │ ├── ios
│ │ │ ├── AppIcon-512@2x.png
│ │ │ ├── AppIcon-20x20@1x.png
│ │ │ ├── AppIcon-20x20@2x.png
│ │ │ ├── AppIcon-20x20@3x.png
│ │ │ ├── AppIcon-29x29@1x.png
│ │ │ ├── AppIcon-29x29@2x.png
│ │ │ ├── AppIcon-29x29@3x.png
│ │ │ ├── AppIcon-40x40@1x.png
│ │ │ ├── AppIcon-40x40@2x.png
│ │ │ ├── AppIcon-40x40@3x.png
│ │ │ ├── AppIcon-60x60@2x.png
│ │ │ ├── AppIcon-60x60@3x.png
│ │ │ ├── AppIcon-76x76@1x.png
│ │ │ ├── AppIcon-76x76@2x.png
│ │ │ ├── AppIcon-20x20@2x-1.png
│ │ │ ├── AppIcon-29x29@2x-1.png
│ │ │ ├── AppIcon-40x40@2x-1.png
│ │ │ └── AppIcon-83.5x83.5@2x.png
│ │ └── android
│ │ │ ├── mipmap-hdpi
│ │ │ ├── ic_launcher.png
│ │ │ ├── ic_launcher_round.png
│ │ │ └── ic_launcher_foreground.png
│ │ │ ├── mipmap-mdpi
│ │ │ ├── ic_launcher.png
│ │ │ ├── ic_launcher_round.png
│ │ │ └── ic_launcher_foreground.png
│ │ │ ├── mipmap-xhdpi
│ │ │ ├── ic_launcher.png
│ │ │ ├── ic_launcher_round.png
│ │ │ └── ic_launcher_foreground.png
│ │ │ ├── mipmap-xxhdpi
│ │ │ ├── ic_launcher.png
│ │ │ ├── ic_launcher_round.png
│ │ │ └── ic_launcher_foreground.png
│ │ │ └── mipmap-xxxhdpi
│ │ │ ├── ic_launcher.png
│ │ │ ├── ic_launcher_round.png
│ │ │ └── ic_launcher_foreground.png
│ ├── src
│ │ ├── lib.rs
│ │ ├── core.rs
│ │ ├── shortcuts.rs
│ │ ├── commands.rs
│ │ ├── main.rs
│ │ └── menu.rs
│ ├── .gitignore
│ ├── capabilities
│ │ └── default.json
│ ├── tauri.conf.json
│ └── Cargo.toml
└── shift-font
│ ├── src
│ ├── lib.rs
│ ├── entity.rs
│ ├── path.rs
│ ├── glyph.rs
│ ├── font.rs
│ ├── contour.rs
│ ├── font_service.rs
│ └── otf_ttf.rs
│ └── Cargo.toml
├── gen
├── charsets
│ ├── .python-version
│ ├── .gitignore
│ ├── README.md
│ ├── pyproject.toml
│ ├── main.py
│ └── charsets.py
└── README.md
├── .husky
└── pre-commit
├── .prettierignore
├── apps
├── browser
│ └── README.md
└── desktop
│ ├── components
│ ├── Layout.tsx
│ ├── Titlebar.tsx
│ ├── SidePane.tsx
│ ├── Toolbar.tsx
│ ├── StaticScene.tsx
│ ├── InteractiveScene.tsx
│ ├── GlyphGrid.tsx
│ ├── NavigationPane.tsx
│ ├── Metrics.tsx
│ ├── ui
│ │ └── tooltip.tsx
│ ├── EditorView.tsx
│ └── ToolsPane.tsx
│ ├── vite-env.d.ts
│ ├── postcss.config.js
│ ├── public
│ ├── canvaskit.wasm
│ └── cursors
│ │ ├── pen@1.svg
│ │ └── pen@2.svg
│ ├── assets
│ ├── fonts
│ │ └── Inter-VariableFont.ttf
│ └── toolbar
│ │ ├── info.svg
│ │ ├── select.svg
│ │ ├── shape.svg
│ │ ├── pen.svg
│ │ ├── hand.svg
│ │ └── grid.svg
│ ├── types
│ ├── svg.d.ts
│ ├── common.ts
│ ├── handle.ts
│ ├── nudge.ts
│ ├── events.ts
│ ├── tool.ts
│ ├── segments.ts
│ ├── edit.ts
│ ├── math.ts
│ └── graphics.ts
│ ├── data
│ └── charsets
│ │ └── index.ts
│ ├── index.css
│ ├── tailwind.config.js
│ ├── lib
│ ├── core
│ │ ├── EditActions.test.ts
│ │ ├── EntityId.ts
│ │ ├── UndoManager.ts
│ │ ├── EventEmitter.test.ts
│ │ ├── common.ts
│ │ ├── EditEngine.ts
│ │ ├── EventEmitter.ts
│ │ ├── EditActions.ts
│ │ ├── PatternMatcher.ts
│ │ ├── PatternParser.ts
│ │ ├── EditEngine.test.ts
│ │ ├── RuleTable.ts
│ │ └── Contour.test.ts
│ ├── utils.ts
│ ├── graphics
│ │ ├── backends
│ │ │ └── errors.ts
│ │ └── Path.ts
│ ├── math
│ │ ├── circle.ts
│ │ ├── shape.ts
│ │ ├── point.ts
│ │ ├── line.ts
│ │ ├── rect.test.ts
│ │ ├── vector.ts
│ │ └── rect.ts
│ ├── editor
│ │ ├── FrameHandler.ts
│ │ ├── Painter.ts
│ │ ├── Viewport.ts
│ │ ├── ContourManager.ts
│ │ └── Scene.ts
│ ├── tools
│ │ ├── tools.ts
│ │ ├── Hand.ts
│ │ ├── Shape.ts
│ │ ├── Pen.ts
│ │ └── Select.ts
│ ├── utils
│ │ └── utils.ts
│ └── styles
│ │ └── style.ts
│ ├── tsconfig.node.json
│ ├── main.tsx
│ ├── app
│ ├── App.tsx
│ ├── App.css
│ └── routes.ts
│ ├── views
│ ├── Home.tsx
│ ├── FontInfo.tsx
│ └── Editor.tsx
│ ├── index.html
│ ├── components.json
│ ├── store
│ └── store.ts
│ ├── tsconfig.json
│ ├── package.json
│ ├── context
│ └── CanvasContext.tsx
│ └── vite.config.ts
├── pnpm-workspace.yaml
├── .cargo
└── config.toml
├── scripts
└── rebuild_types.sh
├── Cargo.toml
├── .gitignore
├── turbo.json
├── package.json
├── .eslintrc.json
└── README.md
/.nvmrc:
--------------------------------------------------------------------------------
1 | lts/jod
--------------------------------------------------------------------------------
/.taurignore:
--------------------------------------------------------------------------------
1 | !crates/*
--------------------------------------------------------------------------------
/packages/shared/README.md:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/crates/shift-unicode/src/unicode.rs:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/gen/charsets/.python-version:
--------------------------------------------------------------------------------
1 | 3.10
2 |
--------------------------------------------------------------------------------
/crates/shift-unicode/build.rs:
--------------------------------------------------------------------------------
1 | fn main() {}
2 |
--------------------------------------------------------------------------------
/crates/shift-unicode/src/lib.rs:
--------------------------------------------------------------------------------
1 | mod unicode;
2 |
--------------------------------------------------------------------------------
/gen/charsets/.gitignore:
--------------------------------------------------------------------------------
1 | __pycache__
2 | .venv
--------------------------------------------------------------------------------
/crates/shift-events/src/lib.rs:
--------------------------------------------------------------------------------
1 | pub mod events;
2 |
--------------------------------------------------------------------------------
/crates/shift-editor/src/lib.rs:
--------------------------------------------------------------------------------
1 | pub mod editor;
2 |
3 |
--------------------------------------------------------------------------------
/.husky/pre-commit:
--------------------------------------------------------------------------------
1 | pnpm format
2 | pnpm lint
3 | pnpm test
4 |
--------------------------------------------------------------------------------
/.prettierignore:
--------------------------------------------------------------------------------
1 | node_modules
2 | dist
3 | build
4 | src-tauri
--------------------------------------------------------------------------------
/gen/README.md:
--------------------------------------------------------------------------------
1 | any packages that generate code live here
2 |
--------------------------------------------------------------------------------
/apps/browser/README.md:
--------------------------------------------------------------------------------
1 | future potential to ship this in the browser
2 |
--------------------------------------------------------------------------------
/apps/desktop/components/Layout.tsx:
--------------------------------------------------------------------------------
1 | export const Layout = () => {};
2 |
--------------------------------------------------------------------------------
/apps/desktop/components/Titlebar.tsx:
--------------------------------------------------------------------------------
1 | export const Titlebar = () => {};
2 |
--------------------------------------------------------------------------------
/crates/shift-tauri/build.rs:
--------------------------------------------------------------------------------
1 | fn main() {
2 | tauri_build::build()
3 | }
4 |
--------------------------------------------------------------------------------
/gen/charsets/README.md:
--------------------------------------------------------------------------------
1 | Generates unicode data from the unicode database
2 |
--------------------------------------------------------------------------------
/apps/desktop/vite-env.d.ts:
--------------------------------------------------------------------------------
1 | ///
2 |
--------------------------------------------------------------------------------
/pnpm-workspace.yaml:
--------------------------------------------------------------------------------
1 | packages:
2 | - "apps/*"
3 | - "crates/*"
4 | - "packages/*"
5 |
--------------------------------------------------------------------------------
/.cargo/config.toml:
--------------------------------------------------------------------------------
1 | [env]
2 | TS_RS_EXPORT_DIR = { value = "./packages/shared/src/types", relative = true }
3 |
--------------------------------------------------------------------------------
/apps/desktop/postcss.config.js:
--------------------------------------------------------------------------------
1 | export default {
2 | plugins: {
3 | autoprefixer: {},
4 | },
5 | };
6 |
--------------------------------------------------------------------------------
/apps/desktop/public/canvaskit.wasm:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/shift-editor/shift/HEAD/apps/desktop/public/canvaskit.wasm
--------------------------------------------------------------------------------
/crates/shift-tauri/icons/32x32.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/shift-editor/shift/HEAD/crates/shift-tauri/icons/32x32.png
--------------------------------------------------------------------------------
/crates/shift-tauri/icons/icon.icns:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/shift-editor/shift/HEAD/crates/shift-tauri/icons/icon.icns
--------------------------------------------------------------------------------
/crates/shift-tauri/icons/icon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/shift-editor/shift/HEAD/crates/shift-tauri/icons/icon.ico
--------------------------------------------------------------------------------
/crates/shift-tauri/icons/icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/shift-editor/shift/HEAD/crates/shift-tauri/icons/icon.png
--------------------------------------------------------------------------------
/crates/shift-tauri/icons/128x128.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/shift-editor/shift/HEAD/crates/shift-tauri/icons/128x128.png
--------------------------------------------------------------------------------
/crates/shift-tauri/icons/128x128@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/shift-editor/shift/HEAD/crates/shift-tauri/icons/128x128@2x.png
--------------------------------------------------------------------------------
/crates/shift-tauri/icons/StoreLogo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/shift-editor/shift/HEAD/crates/shift-tauri/icons/StoreLogo.png
--------------------------------------------------------------------------------
/crates/shift-tauri/icons/Square30x30Logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/shift-editor/shift/HEAD/crates/shift-tauri/icons/Square30x30Logo.png
--------------------------------------------------------------------------------
/crates/shift-tauri/icons/Square44x44Logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/shift-editor/shift/HEAD/crates/shift-tauri/icons/Square44x44Logo.png
--------------------------------------------------------------------------------
/crates/shift-tauri/icons/Square71x71Logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/shift-editor/shift/HEAD/crates/shift-tauri/icons/Square71x71Logo.png
--------------------------------------------------------------------------------
/crates/shift-tauri/icons/Square89x89Logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/shift-editor/shift/HEAD/crates/shift-tauri/icons/Square89x89Logo.png
--------------------------------------------------------------------------------
/crates/shift-unicode/Cargo.toml:
--------------------------------------------------------------------------------
1 | [package]
2 | name = "shift-unicode"
3 | version = "0.1.0"
4 | edition = "2024"
5 |
6 | [dependencies]
7 |
--------------------------------------------------------------------------------
/crates/shift-tauri/icons/Square107x107Logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/shift-editor/shift/HEAD/crates/shift-tauri/icons/Square107x107Logo.png
--------------------------------------------------------------------------------
/crates/shift-tauri/icons/Square142x142Logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/shift-editor/shift/HEAD/crates/shift-tauri/icons/Square142x142Logo.png
--------------------------------------------------------------------------------
/crates/shift-tauri/icons/Square150x150Logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/shift-editor/shift/HEAD/crates/shift-tauri/icons/Square150x150Logo.png
--------------------------------------------------------------------------------
/crates/shift-tauri/icons/Square284x284Logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/shift-editor/shift/HEAD/crates/shift-tauri/icons/Square284x284Logo.png
--------------------------------------------------------------------------------
/crates/shift-tauri/icons/Square310x310Logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/shift-editor/shift/HEAD/crates/shift-tauri/icons/Square310x310Logo.png
--------------------------------------------------------------------------------
/crates/shift-tauri/icons/ios/AppIcon-512@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/shift-editor/shift/HEAD/crates/shift-tauri/icons/ios/AppIcon-512@2x.png
--------------------------------------------------------------------------------
/apps/desktop/assets/fonts/Inter-VariableFont.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/shift-editor/shift/HEAD/apps/desktop/assets/fonts/Inter-VariableFont.ttf
--------------------------------------------------------------------------------
/crates/shift-tauri/icons/ios/AppIcon-20x20@1x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/shift-editor/shift/HEAD/crates/shift-tauri/icons/ios/AppIcon-20x20@1x.png
--------------------------------------------------------------------------------
/crates/shift-tauri/icons/ios/AppIcon-20x20@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/shift-editor/shift/HEAD/crates/shift-tauri/icons/ios/AppIcon-20x20@2x.png
--------------------------------------------------------------------------------
/crates/shift-tauri/icons/ios/AppIcon-20x20@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/shift-editor/shift/HEAD/crates/shift-tauri/icons/ios/AppIcon-20x20@3x.png
--------------------------------------------------------------------------------
/crates/shift-tauri/icons/ios/AppIcon-29x29@1x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/shift-editor/shift/HEAD/crates/shift-tauri/icons/ios/AppIcon-29x29@1x.png
--------------------------------------------------------------------------------
/crates/shift-tauri/icons/ios/AppIcon-29x29@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/shift-editor/shift/HEAD/crates/shift-tauri/icons/ios/AppIcon-29x29@2x.png
--------------------------------------------------------------------------------
/crates/shift-tauri/icons/ios/AppIcon-29x29@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/shift-editor/shift/HEAD/crates/shift-tauri/icons/ios/AppIcon-29x29@3x.png
--------------------------------------------------------------------------------
/crates/shift-tauri/icons/ios/AppIcon-40x40@1x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/shift-editor/shift/HEAD/crates/shift-tauri/icons/ios/AppIcon-40x40@1x.png
--------------------------------------------------------------------------------
/crates/shift-tauri/icons/ios/AppIcon-40x40@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/shift-editor/shift/HEAD/crates/shift-tauri/icons/ios/AppIcon-40x40@2x.png
--------------------------------------------------------------------------------
/crates/shift-tauri/icons/ios/AppIcon-40x40@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/shift-editor/shift/HEAD/crates/shift-tauri/icons/ios/AppIcon-40x40@3x.png
--------------------------------------------------------------------------------
/crates/shift-tauri/icons/ios/AppIcon-60x60@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/shift-editor/shift/HEAD/crates/shift-tauri/icons/ios/AppIcon-60x60@2x.png
--------------------------------------------------------------------------------
/crates/shift-tauri/icons/ios/AppIcon-60x60@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/shift-editor/shift/HEAD/crates/shift-tauri/icons/ios/AppIcon-60x60@3x.png
--------------------------------------------------------------------------------
/crates/shift-tauri/icons/ios/AppIcon-76x76@1x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/shift-editor/shift/HEAD/crates/shift-tauri/icons/ios/AppIcon-76x76@1x.png
--------------------------------------------------------------------------------
/crates/shift-tauri/icons/ios/AppIcon-76x76@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/shift-editor/shift/HEAD/crates/shift-tauri/icons/ios/AppIcon-76x76@2x.png
--------------------------------------------------------------------------------
/crates/shift-tauri/icons/ios/AppIcon-20x20@2x-1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/shift-editor/shift/HEAD/crates/shift-tauri/icons/ios/AppIcon-20x20@2x-1.png
--------------------------------------------------------------------------------
/crates/shift-tauri/icons/ios/AppIcon-29x29@2x-1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/shift-editor/shift/HEAD/crates/shift-tauri/icons/ios/AppIcon-29x29@2x-1.png
--------------------------------------------------------------------------------
/crates/shift-tauri/icons/ios/AppIcon-40x40@2x-1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/shift-editor/shift/HEAD/crates/shift-tauri/icons/ios/AppIcon-40x40@2x-1.png
--------------------------------------------------------------------------------
/crates/shift-tauri/icons/ios/AppIcon-83.5x83.5@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/shift-editor/shift/HEAD/crates/shift-tauri/icons/ios/AppIcon-83.5x83.5@2x.png
--------------------------------------------------------------------------------
/apps/desktop/types/svg.d.ts:
--------------------------------------------------------------------------------
1 | declare module '*.svg' {
2 | const ReactComponent: React.FC>;
3 | export default ReactComponent;
4 | }
5 |
--------------------------------------------------------------------------------
/crates/shift-editor/Cargo.toml:
--------------------------------------------------------------------------------
1 | [package]
2 | name = "shift-editor"
3 | version = "0.1.0"
4 | edition = "2024"
5 |
6 | [dependencies]
7 | shift-font.workspace = true
8 |
--------------------------------------------------------------------------------
/crates/shift-tauri/icons/android/mipmap-hdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/shift-editor/shift/HEAD/crates/shift-tauri/icons/android/mipmap-hdpi/ic_launcher.png
--------------------------------------------------------------------------------
/crates/shift-tauri/icons/android/mipmap-mdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/shift-editor/shift/HEAD/crates/shift-tauri/icons/android/mipmap-mdpi/ic_launcher.png
--------------------------------------------------------------------------------
/crates/shift-tauri/icons/android/mipmap-xhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/shift-editor/shift/HEAD/crates/shift-tauri/icons/android/mipmap-xhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/crates/shift-tauri/icons/android/mipmap-xxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/shift-editor/shift/HEAD/crates/shift-tauri/icons/android/mipmap-xxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/crates/shift-tauri/icons/android/mipmap-xxxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/shift-editor/shift/HEAD/crates/shift-tauri/icons/android/mipmap-xxxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/apps/desktop/data/charsets/index.ts:
--------------------------------------------------------------------------------
1 | import { ADOBE_LATIN_1 } from './adobe-latin-1';
2 |
3 | export { ADOBE_LATIN_1 };
4 |
5 | export const CHARSETS = {
6 | ADOBE_LATIN_1,
7 | };
8 |
--------------------------------------------------------------------------------
/apps/desktop/types/common.ts:
--------------------------------------------------------------------------------
1 | export type Result = { success: true; data: T } | { success: false; error: E };
2 |
3 | export type Svg = React.FC>;
4 |
--------------------------------------------------------------------------------
/apps/desktop/types/handle.ts:
--------------------------------------------------------------------------------
1 | export type HandleType = 'corner' | 'smooth' | 'control' | 'direction' | 'first' | 'last';
2 | export type HandleState = 'idle' | 'hovered' | 'selected';
3 |
--------------------------------------------------------------------------------
/crates/shift-font/src/lib.rs:
--------------------------------------------------------------------------------
1 | pub mod contour;
2 | pub mod entity;
3 | pub mod font;
4 | pub mod font_service;
5 | pub mod glyph;
6 | pub mod otf_ttf;
7 | pub mod path;
8 | pub mod ufo;
9 |
--------------------------------------------------------------------------------
/crates/shift-tauri/icons/android/mipmap-hdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/shift-editor/shift/HEAD/crates/shift-tauri/icons/android/mipmap-hdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/crates/shift-tauri/icons/android/mipmap-mdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/shift-editor/shift/HEAD/crates/shift-tauri/icons/android/mipmap-mdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/crates/shift-tauri/icons/android/mipmap-xhdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/shift-editor/shift/HEAD/crates/shift-tauri/icons/android/mipmap-xhdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/crates/shift-tauri/src/lib.rs:
--------------------------------------------------------------------------------
1 | #![cfg_attr(not(debug_assertions), windows_subsystem = "windows")]
2 |
3 | pub mod commands;
4 | pub mod core;
5 | pub mod menu;
6 | pub mod shortcuts;
7 |
--------------------------------------------------------------------------------
/apps/desktop/index.css:
--------------------------------------------------------------------------------
1 | @import 'tailwindcss';
2 | @import 'tw-animate-css';
3 |
4 | @theme {
5 | --font-ui: 'Inter';
6 | --text-ui: 0.85rem;
7 | --color-secondary: #3a3a3a;
8 | }
9 |
--------------------------------------------------------------------------------
/crates/shift-tauri/icons/android/mipmap-xxhdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/shift-editor/shift/HEAD/crates/shift-tauri/icons/android/mipmap-xxhdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/crates/shift-tauri/icons/android/mipmap-xxxhdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/shift-editor/shift/HEAD/crates/shift-tauri/icons/android/mipmap-xxxhdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/crates/shift-tauri/icons/android/mipmap-hdpi/ic_launcher_foreground.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/shift-editor/shift/HEAD/crates/shift-tauri/icons/android/mipmap-hdpi/ic_launcher_foreground.png
--------------------------------------------------------------------------------
/crates/shift-tauri/icons/android/mipmap-mdpi/ic_launcher_foreground.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/shift-editor/shift/HEAD/crates/shift-tauri/icons/android/mipmap-mdpi/ic_launcher_foreground.png
--------------------------------------------------------------------------------
/crates/shift-tauri/icons/android/mipmap-xhdpi/ic_launcher_foreground.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/shift-editor/shift/HEAD/crates/shift-tauri/icons/android/mipmap-xhdpi/ic_launcher_foreground.png
--------------------------------------------------------------------------------
/crates/shift-tauri/icons/android/mipmap-xxhdpi/ic_launcher_foreground.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/shift-editor/shift/HEAD/crates/shift-tauri/icons/android/mipmap-xxhdpi/ic_launcher_foreground.png
--------------------------------------------------------------------------------
/crates/shift-tauri/icons/android/mipmap-xxxhdpi/ic_launcher_foreground.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/shift-editor/shift/HEAD/crates/shift-tauri/icons/android/mipmap-xxxhdpi/ic_launcher_foreground.png
--------------------------------------------------------------------------------
/apps/desktop/tailwind.config.js:
--------------------------------------------------------------------------------
1 | /** @type {import('tailwindcss').Config} */
2 | export default {
3 | content: ['./index.html', './app/**/*.{js,ts,jsx,tsx}'],
4 | theme: {},
5 | plugins: [],
6 | };
7 |
--------------------------------------------------------------------------------
/packages/shared/src/types/PointType.ts:
--------------------------------------------------------------------------------
1 | // This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually.
2 |
3 | export type PointType = "onCurve" | "offCurve";
4 |
--------------------------------------------------------------------------------
/apps/desktop/lib/core/EditActions.test.ts:
--------------------------------------------------------------------------------
1 | import { describe, it } from 'vitest';
2 |
3 | describe('maintainTangency', () => {
4 | it('should maintain tangency when moving a selected point', () => {});
5 | });
6 |
--------------------------------------------------------------------------------
/apps/desktop/lib/utils.ts:
--------------------------------------------------------------------------------
1 | import { clsx, type ClassValue } from 'clsx';
2 | import { twMerge } from 'tailwind-merge';
3 |
4 | export function cn(...inputs: ClassValue[]) {
5 | return twMerge(clsx(inputs));
6 | }
7 |
--------------------------------------------------------------------------------
/packages/shared/src/types/EntityId.ts:
--------------------------------------------------------------------------------
1 | // This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually.
2 |
3 | export type EntityId = { parentId: number, id: number, };
4 |
--------------------------------------------------------------------------------
/packages/shared/src/types/FontLoadedEvent.ts:
--------------------------------------------------------------------------------
1 | // This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually.
2 |
3 | export type FontLoadedEvent = { fileName: string, };
4 |
--------------------------------------------------------------------------------
/apps/desktop/types/nudge.ts:
--------------------------------------------------------------------------------
1 | export type NudgeMagnitude = 'small' | 'medium' | 'large';
2 | export const NUDGES_VALUES: Record = {
3 | small: 1,
4 | medium: 10,
5 | large: 100,
6 | } as const;
7 |
--------------------------------------------------------------------------------
/apps/desktop/components/SidePane.tsx:
--------------------------------------------------------------------------------
1 | export const SidePane = () => {
2 | return (
3 |
4 |
7 |
8 | );
9 | };
10 |
--------------------------------------------------------------------------------
/packages/shared/src/types/FontCompiledEvent.ts:
--------------------------------------------------------------------------------
1 | // This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually.
2 |
3 | export type FontCompiledEvent = { fileName: string, fontPath: string, };
4 |
--------------------------------------------------------------------------------
/packages/shared/src/types/FontMetadata.ts:
--------------------------------------------------------------------------------
1 | // This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually.
2 |
3 | export type FontMetadata = { family: string, styleName: string, version: number, };
4 |
--------------------------------------------------------------------------------
/crates/shift-events/Cargo.toml:
--------------------------------------------------------------------------------
1 | [package]
2 | name = "shift-events"
3 | version = "0.1.0"
4 | edition = "2024"
5 |
6 | [dependencies]
7 | serde = { version = "1", features = ["derive"] }
8 | ts-rs = "10.1"
9 | shift-font.workspace = true
10 |
--------------------------------------------------------------------------------
/crates/shift-tauri/.gitignore:
--------------------------------------------------------------------------------
1 | # Generated by Cargo
2 | # will have compiled files and executables
3 | /target/
4 |
5 | # Generated by Tauri
6 | # will have schema files for capabilities auto-completion
7 | /gen/schemas
8 |
9 | .vscode
10 | .bin
--------------------------------------------------------------------------------
/scripts/rebuild_types.sh:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 |
3 |
4 | pnpm --filter @shift/shared clean
5 |
6 | cargo test -p shift-font export_bindings &
7 | cargo test -p shift-events export_bindings &
8 |
9 | wait
10 |
11 | pnpm --filter @shift/shared build
--------------------------------------------------------------------------------
/packages/shared/src/types/Metrics.ts:
--------------------------------------------------------------------------------
1 | // This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually.
2 |
3 | export type Metrics = { unitsPerEm: number, ascender: number, descender: number, capHeight: number, xHeight: number, };
4 |
--------------------------------------------------------------------------------
/packages/shared/src/types/PointsAddedEvent.ts:
--------------------------------------------------------------------------------
1 | // This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually.
2 | import type { EntityId } from "./EntityId";
3 |
4 | export type PointsAddedEvent = { pointIds: Array, };
5 |
--------------------------------------------------------------------------------
/packages/shared/src/types/PointsMovedEvent.ts:
--------------------------------------------------------------------------------
1 | // This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually.
2 | import type { MovedPoint } from "./MovedPoint";
3 |
4 | export type PointsMovedEvent = { points: Array, };
5 |
--------------------------------------------------------------------------------
/gen/charsets/pyproject.toml:
--------------------------------------------------------------------------------
1 | [project]
2 | name = "unicode"
3 | version = "0.1.0"
4 | description = "Generate unicode tables for Rust"
5 | readme = "README.md"
6 | requires-python = ">=3.10"
7 | dependencies = [
8 | "fonttools>=4.56.0",
9 | "requests>=2.32.3",
10 | ]
11 |
--------------------------------------------------------------------------------
/crates/shift-font/src/entity.rs:
--------------------------------------------------------------------------------
1 | use serde::Serialize;
2 | use ts_rs::TS;
3 |
4 | type Ident = usize;
5 |
6 | #[derive(Serialize, Clone, TS)]
7 | #[ts(export)]
8 | #[serde(rename_all = "camelCase")]
9 | pub struct EntityId {
10 | parent_id: Ident,
11 | id: Ident,
12 | }
13 |
--------------------------------------------------------------------------------
/packages/shared/src/types/IContour.ts:
--------------------------------------------------------------------------------
1 | // This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually.
2 | import type { IContourPoint } from "./IContourPoint";
3 |
4 | export type IContour = { points: Array, closed: boolean, };
5 |
--------------------------------------------------------------------------------
/apps/desktop/tsconfig.node.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "composite": true,
4 | "skipLibCheck": true,
5 | "module": "ESNext",
6 | "moduleResolution": "bundler",
7 | "allowSyntheticDefaultImports": true
8 | },
9 | "include": ["vite.config.ts"]
10 | }
11 |
--------------------------------------------------------------------------------
/packages/shared/src/types/Glyph.ts:
--------------------------------------------------------------------------------
1 | // This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually.
2 | import type { IContour } from "./IContour";
3 |
4 | export type Glyph = { name: string, unicode: number, contours: Array, x_advance: number, };
5 |
--------------------------------------------------------------------------------
/packages/shared/src/types/IContourPoint.ts:
--------------------------------------------------------------------------------
1 | // This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually.
2 | import type { PointType } from "./PointType";
3 |
4 | export type IContourPoint = { pointType: PointType, x: number, y: number, smooth: boolean, };
5 |
--------------------------------------------------------------------------------
/packages/shared/src/types/MovedPoint.ts:
--------------------------------------------------------------------------------
1 | // This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually.
2 | import type { EntityId } from "./EntityId";
3 |
4 | export type MovedPoint = { pointId: EntityId, fromX: number, fromY: number, toX: number, toY: number, };
5 |
--------------------------------------------------------------------------------
/Cargo.toml:
--------------------------------------------------------------------------------
1 | [workspace]
2 | resolver = "2"
3 | members = ["crates/*"]
4 |
5 |
6 | [workspace.dependencies]
7 | shift-events = { path = "crates/shift-events" }
8 | shift-font = { path = "crates/shift-font" }
9 | shift-editor = { path = "crates/shift-editor" }
10 | shift-unicode = { path = "crates/shift-unicode" }
11 |
--------------------------------------------------------------------------------
/crates/shift-tauri/src/core.rs:
--------------------------------------------------------------------------------
1 | use tauri::AppHandle;
2 |
3 | pub fn handle_quit(app: &AppHandle) {
4 | // Add any cleanup logic here before quitting
5 | println!("Quitting Shift font editor...");
6 |
7 | // You can add save prompts, cleanup, etc. here
8 | // For now, just exit
9 | app.exit(0);
10 | }
11 |
--------------------------------------------------------------------------------
/apps/desktop/main.tsx:
--------------------------------------------------------------------------------
1 | import * as React from 'react';
2 |
3 | import { createRoot } from 'react-dom/client';
4 |
5 | import { App } from './app/App';
6 | import './index.css';
7 |
8 | createRoot(document.getElementById('root') as HTMLElement).render(
9 |
10 |
11 |
12 | );
13 |
--------------------------------------------------------------------------------
/crates/shift-font/Cargo.toml:
--------------------------------------------------------------------------------
1 | [package]
2 | name = "shift-font"
3 | version = "0.1.0"
4 | edition = "2024"
5 |
6 | [dependencies]
7 | write-fonts = { version = "0.36.3", features = ["read"] }
8 | skrifa = "0.28.1"
9 | norad = "0.15.0"
10 | serde = { version = "1", features = ["derive"] }
11 | ts-rs = "10.1"
12 | fontc = { git = "https://github.com/googlefonts/fontc" }
13 |
--------------------------------------------------------------------------------
/packages/shared/src/types/Font.ts:
--------------------------------------------------------------------------------
1 | // This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually.
2 | import type { FontMetadata } from "./FontMetadata";
3 | import type { Glyph } from "./Glyph";
4 | import type { Metrics } from "./Metrics";
5 |
6 | export type Font = { metadata: FontMetadata, metrics: Metrics, glyphs: { [key in number]?: Glyph }, };
7 |
--------------------------------------------------------------------------------
/apps/desktop/types/events.ts:
--------------------------------------------------------------------------------
1 | export type EventName = 'points:added' | 'points:moved' | 'points:removed' | 'segment:upgraded';
2 | export type EventHandler = (data: T) => void;
3 |
4 | export interface IEventEmitter {
5 | on(event: EventName, handler: EventHandler): void;
6 | emit(event: EventName, data: T): void;
7 | off(event: EventName, handler: EventHandler): void;
8 | }
9 |
--------------------------------------------------------------------------------
/apps/desktop/lib/graphics/backends/errors.ts:
--------------------------------------------------------------------------------
1 | export class SkiaGraphicsContextError extends Error {
2 | constructor(message: string) {
3 | super(message);
4 | this.name = 'SkiaGraphicsContextError ';
5 | }
6 | }
7 |
8 | export class SkiaRendererError extends Error {
9 | constructor(message: string) {
10 | super(message);
11 | this.name = 'SkiaRendererError ';
12 | }
13 | }
14 |
--------------------------------------------------------------------------------
/crates/shift-tauri/src/shortcuts.rs:
--------------------------------------------------------------------------------
1 | use crate::core;
2 | use tauri::AppHandle;
3 | use tauri_plugin_global_shortcut::{Code, Modifiers, Shortcut};
4 |
5 | pub fn handle_shortcut(app: &AppHandle, shortcut: &Shortcut) {
6 | if shortcut.matches(Modifiers::META, Code::KeyQ) {
7 | println!("Force quit triggered via global shortcut");
8 | core::handle_quit(app);
9 | }
10 | }
11 |
--------------------------------------------------------------------------------
/apps/desktop/assets/toolbar/info.svg:
--------------------------------------------------------------------------------
1 |
4 |
--------------------------------------------------------------------------------
/apps/desktop/components/Toolbar.tsx:
--------------------------------------------------------------------------------
1 | import { NavigationPane } from './NavigationPane';
2 | import { ToolsPane } from './ToolsPane';
3 |
4 | export const Toolbar = () => {
5 | return (
6 |
7 |
8 |
9 |
10 |
11 | );
12 | };
13 |
--------------------------------------------------------------------------------
/packages/shared/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "outDir": "./dist",
4 | "declaration": true,
5 | "target": "ES2020",
6 | "module": "ESNext",
7 | "moduleResolution": "node",
8 | "esModuleInterop": true,
9 | "skipLibCheck": true,
10 | "strict": true
11 | },
12 | "include": ["src/**/*"],
13 | "exclude": ["dist"]
14 | }
--------------------------------------------------------------------------------
/apps/desktop/lib/math/circle.ts:
--------------------------------------------------------------------------------
1 | import { Shape } from '@/lib/math/shape';
2 |
3 | export class Circle extends Shape {
4 | #radius: number;
5 |
6 | constructor(x: number, y: number, radius: number) {
7 | super(x, y);
8 | this.#radius = radius;
9 | }
10 |
11 | public get radius(): number {
12 | return this.#radius;
13 | }
14 |
15 | hit(): boolean {
16 | return false;
17 | }
18 | }
19 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # Logs
2 | logs
3 | *.log
4 | npm-debug.log*
5 | yarn-debug.log*
6 | yarn-error.log*
7 | pnpm-debug.log*
8 | lerna-debug.log*
9 |
10 | node_modules
11 | dist
12 | dist-ssr
13 | *.local
14 |
15 | # Editor directories and files
16 | !.vscode/extensions.json
17 | .idea
18 | .DS_Store
19 | *.suo
20 | *.ntvs*
21 | *.njsproj
22 | *.sln
23 | *.sw?
24 | .cursorrules
25 | .vscode
26 |
27 | target*
28 | .turbo
29 | .bin
--------------------------------------------------------------------------------
/apps/desktop/components/StaticScene.tsx:
--------------------------------------------------------------------------------
1 | import { useContext } from 'react';
2 |
3 | import { CanvasContext } from '@/context/CanvasContext';
4 |
5 | export const StaticScene = () => {
6 | const { staticCanvasRef } = useContext(CanvasContext);
7 |
8 | return (
9 |
14 | );
15 | };
16 |
--------------------------------------------------------------------------------
/crates/shift-tauri/capabilities/default.json:
--------------------------------------------------------------------------------
1 | {
2 | "$schema": "../gen/schemas/desktop-schema.json",
3 | "identifier": "default",
4 | "description": "Capability for the main window",
5 | "windows": ["main"],
6 | "permissions": [
7 | "core:default",
8 | "shell:allow-open",
9 | "log:default",
10 | "global-shortcut:allow-is-registered",
11 | "global-shortcut:allow-register",
12 | "global-shortcut:allow-unregister"
13 | ]
14 | }
15 |
--------------------------------------------------------------------------------
/packages/shared/src/types/PathCommand.ts:
--------------------------------------------------------------------------------
1 | // This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually.
2 |
3 | export type PathCommand = { "type": "moveTo", x: number, y: number, } | { "type": "lineTo", x: number, y: number, } | { "type": "cubicTo", cp1x: number, cp1y: number, cp2x: number, cp2y: number, x: number, y: number, } | { "type": "quadTo", cp1x: number, cp1y: number, x: number, y: number, } | { "type": "close" };
4 |
--------------------------------------------------------------------------------
/apps/desktop/app/App.tsx:
--------------------------------------------------------------------------------
1 | import './App.css';
2 | import { HashRouter, Route, Routes } from 'react-router-dom';
3 |
4 | import { routes } from './routes';
5 |
6 | export const App = () => {
7 | return (
8 |
9 |
10 | {routes.map((route) => (
11 | } />
12 | ))}
13 |
14 |
15 | );
16 | };
17 |
18 | export default App;
19 |
--------------------------------------------------------------------------------
/apps/desktop/views/Home.tsx:
--------------------------------------------------------------------------------
1 | import { GlyphGrid } from '@/components/GlyphGrid';
2 | import { Toolbar } from '@/components/Toolbar';
3 |
4 | export const Home = () => {
5 | return (
6 |
7 |
8 |
13 |
14 | );
15 | };
16 |
--------------------------------------------------------------------------------
/apps/desktop/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | Shift
8 |
9 |
10 |
11 |
12 |
13 |
14 |