Compare commits
68 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 1babf4977d | |||
| 0d4a55ed1f | |||
| 10dd25fd26 | |||
| 135f6eb156 | |||
| 4499ba4809 | |||
| fff435748f | |||
| eec76d8792 | |||
| 7a86cd065f | |||
| 834a086e09 | |||
| 298723b87e | |||
| 0956c0e569 | |||
| 30ef51ace3 | |||
| 8aa2677ffc | |||
| 5c25311fdf | |||
| a55ef07837 | |||
| 09bbb2bb76 | |||
| 4ff7dbde28 | |||
| 0d7089f840 | |||
| 8a32259fdc | |||
| ee481cc744 | |||
| 196e13856c | |||
| 2029e07965 | |||
| 4955c58098 | |||
| c63a5b0abb | |||
| 8f7db7bc4c | |||
| 3813319b42 | |||
| f2a61c74ad | |||
| 1fce61fe50 | |||
| 1028c96291 | |||
| 043c160546 | |||
| 445828c8bf | |||
| 66fd3f94a1 | |||
| 9bf5f6197c | |||
| bd48389313 | |||
| 30a6c098e7 | |||
| 42e64f84b8 | |||
| 124d893fe5 | |||
| e692fcfbf8 | |||
| 321486d19e | |||
| 6f3d00ae6d | |||
| 420eeefe59 | |||
| a5c360bf30 | |||
| 93d4d03ef5 | |||
| 59435e4ee8 | |||
| cad9759288 | |||
| d3940070ed | |||
| 320fb069f7 | |||
| d6c1df83ed | |||
| 0b29866a3e | |||
| 9a70d50924 | |||
| 68741971f1 | |||
| bfae141c75 | |||
| 844b55f7b2 | |||
| 0c226a60bc | |||
| 2dd2079309 | |||
| 6f14cd709a | |||
| 06b5464fd6 | |||
| dc2d35f1c5 | |||
| 0823ed98af | |||
| 7b6eb72e66 | |||
| 53e9951957 | |||
| 44fc9b5ead | |||
| a86034b38d | |||
| c1bb4a9197 | |||
| 77244583f0 | |||
| f26cecc4bf | |||
| 732a29a79f | |||
| 258531d577 |
@@ -48,6 +48,51 @@
|
||||
"doc",
|
||||
"design"
|
||||
]
|
||||
},
|
||||
{
|
||||
"login": "CandySunPlus",
|
||||
"name": "NikSun",
|
||||
"avatar_url": "https://avatars0.githubusercontent.com/u/502700?v=4",
|
||||
"profile": "https://github.com/CandySunPlus",
|
||||
"contributions": [
|
||||
"design"
|
||||
]
|
||||
},
|
||||
{
|
||||
"login": "Jakob6174",
|
||||
"name": "Jakob Pearson",
|
||||
"avatar_url": "https://avatars3.githubusercontent.com/u/40262817?v=4",
|
||||
"profile": "https://github.com/Jakob6174",
|
||||
"contributions": [
|
||||
"code"
|
||||
]
|
||||
},
|
||||
{
|
||||
"login": "Kilua99",
|
||||
"name": "kilua99",
|
||||
"avatar_url": "https://avatars.githubusercontent.com/u/44760686?v=4",
|
||||
"profile": "https://github.com/Kilua99",
|
||||
"contributions": [
|
||||
"doc"
|
||||
]
|
||||
},
|
||||
{
|
||||
"login": "GlorifiedBicycle",
|
||||
"name": "Reland Boyle",
|
||||
"avatar_url": "https://avatars.githubusercontent.com/u/71753585?v=4",
|
||||
"profile": "https://github.com/GlorifiedBicycle",
|
||||
"contributions": [
|
||||
"doc"
|
||||
]
|
||||
},
|
||||
{
|
||||
"login": "killua99",
|
||||
"name": "Luigi",
|
||||
"avatar_url": "https://avatars.githubusercontent.com/u/457822?v=4",
|
||||
"profile": "http://killua.me/",
|
||||
"contributions": [
|
||||
"doc"
|
||||
]
|
||||
}
|
||||
],
|
||||
"contributorsPerLine": 7
|
||||
|
||||
@@ -1,17 +1,14 @@
|
||||
module.exports = {
|
||||
env: {
|
||||
es6: true,
|
||||
node: true
|
||||
node: true,
|
||||
},
|
||||
extends: 'eslint:recommended',
|
||||
extends: ['eslint:recommended', 'prettier'],
|
||||
parserOptions: {
|
||||
sourceType: 'module'
|
||||
sourceType: 'module',
|
||||
},
|
||||
rules: {
|
||||
indent: ['error', 2],
|
||||
'linebreak-style': ['error', 'unix'],
|
||||
quotes: ['error', 'single'],
|
||||
semi: ['error', 'always'],
|
||||
'no-console': 'off'
|
||||
}
|
||||
};
|
||||
'no-console': 'off',
|
||||
},
|
||||
}
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
root: ./docs
|
||||
@@ -0,0 +1,47 @@
|
||||
---
|
||||
name: New ligature
|
||||
about: Use this template for requesting new ligatures.
|
||||
title: "Create `[LIGATURE NAME]` ligature"
|
||||
labels: enhancement
|
||||
---
|
||||
|
||||
<!-- Please only request a single ligature per issue, unless you would like something which has both symmetrical pairs (e.g. {{ and }}) -->
|
||||
|
||||
## Request preferences
|
||||
|
||||
* Weight requested: _State which weight you would like, and whether it is for SSm or not._
|
||||
|
||||
|
||||
## Ligature description
|
||||
|
||||
_Please descirbe the ligature here as best you can. Feel free to use images/screenshots to help us get ideas of how to implement it._
|
||||
|
||||
---
|
||||
|
||||
### Ligature variations
|
||||
|
||||
Due to how development is handled, not all ligatures are created at the same time. However, we will get to them all eventually. If you would like to help us develop ligatures, please reach out to us via email at kiliman@gmail.com
|
||||
|
||||
#### Operator Mono
|
||||
|
||||
- [ ] XLight
|
||||
- [ ] XLight Italic
|
||||
- [ ] Light
|
||||
- [ ] Light Italic
|
||||
- [ ] Book
|
||||
- [ ] Book Italic
|
||||
- [ ] Medium
|
||||
- [ ] Medium Italic
|
||||
- [ ] Bold
|
||||
- [ ] Bold Italic
|
||||
|
||||
#### Operator Mono SSm
|
||||
|
||||
- [ ] SSm Light
|
||||
- [ ] SSm Light Italic
|
||||
- [ ] SSm Book
|
||||
- [ ] SSm Book Italic
|
||||
- [ ] SSm Medium
|
||||
- [ ] SSm Medium Italic
|
||||
- [ ] SSm Bold
|
||||
- [ ] SSm Bold Italic
|
||||
@@ -1,4 +1,6 @@
|
||||
build
|
||||
node_modules
|
||||
.vscode/launch.json
|
||||
.idea
|
||||
.vscode
|
||||
.DS_Store
|
||||
pnpm-lock.yaml
|
||||
|
||||
@@ -1,4 +1,6 @@
|
||||
{
|
||||
"semi": true,
|
||||
"singleQuote": true
|
||||
"semi": false,
|
||||
"singleQuote": true,
|
||||
"trailingComma": "all",
|
||||
"arrowParens": "avoid"
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# Operator Mono Ligatures
|
||||
|
||||
[](#contributors-)
|
||||
[](#contributors-)
|
||||
|
||||
<img src="./images/operator-mono-lig.png" />
|
||||
|
||||
@@ -10,6 +10,10 @@ those found in the popular [Fira Code](https://github.com/tonsky/FiraCode) font.
|
||||
These ligatures were custom created using [Glyphs](https://glyphsapp.com/).
|
||||
There are even italic versions of the ligatures.
|
||||
|
||||
## 🎉 What's New in Version 2.5
|
||||
|
||||
<img src="./images/new-ligatures-2.5.png"/>
|
||||
|
||||
## 🎉 What's New in Version 2
|
||||
|
||||
<img src="./images/new-ligatures.png"/>
|
||||
@@ -20,6 +24,8 @@ characters properly.
|
||||
|
||||
<img src="./images/caret-position.gif" />
|
||||
|
||||
## 👀 <a href="https://htmlpreview.github.io/?https://github.com/kiliman/operator-mono-lig/blob/master/images/preview/normal/index.html">Click here to see preview images of all ligatures</a>
|
||||
|
||||
With the awesome help from [Mark Skelton](https://github.com/mskelton), we now have the full set of ligatures for
|
||||
the following fonts. Thanks Mark, and thanks to all of you who have been patiently waiting for these ligatures to be completed.
|
||||
|
||||
@@ -54,10 +60,13 @@ Which font weight of Operator Mono do you use? Also note difference between Scre
|
||||
|
||||
- The original _Operator Mono_ font... of course.
|
||||
- Python (v2.7+)
|
||||
- **NOTE**: For Mac, the default system Python v2.7 doesn't work. Make sure you install Python 3.
|
||||
- Node.js
|
||||
- Install _fonttools_ from https://github.com/fonttools/fonttools
|
||||
- Windows/Linux: `pip install fonttools`
|
||||
- Mac: `pip3 install fonttools`
|
||||
- **NOTE**: For Windows you should use a console with administrative permissions if your Python sit under `C:\PythonX`
|
||||
- **NOTE**: For Linux in WSL/WSL2, ensure that _fonttools_ is added to PATH after install. Alternatively, consider installing via `sudo apt install fonttools`.
|
||||
- Mac: `pip3 install fonttools` (from Python 3)
|
||||
|
||||
## Installation
|
||||
|
||||
@@ -94,7 +103,7 @@ If you use Docker, you can also use the executable Docker image [here](https://g
|
||||
docker-compose run --rm operator-mono-lig
|
||||
```
|
||||
|
||||
The image will build and execute the conversion. The new font files will be generated into the `output` folder.
|
||||
The image will build and execute the conversion. The new font files will be generated into the `build` folder.
|
||||
|
||||
## Configure Your Code Editor
|
||||
|
||||
@@ -152,15 +161,22 @@ Thanks goes to these wonderful people ([emoji key](https://allcontributors.org/d
|
||||
<!-- markdownlint-disable -->
|
||||
<table>
|
||||
<tr>
|
||||
<td align="center"><a href="https://github.com/kiliman"><img src="https://avatars3.githubusercontent.com/u/47168?v=4" width="100px;" alt="Kiliman"/><br /><sub><b>Kiliman</b></sub></a><br /><a href="https://github.com/kiliman/operator-mono-lig/commits?author=kiliman" title="Code">💻</a> <a href="https://github.com/kiliman/operator-mono-lig/commits?author=kiliman" title="Documentation">📖</a> <a href="#design-kiliman" title="Design">🎨</a></td>
|
||||
<td align="center"><a href="https://github.com/mskelton"><img src="https://avatars3.githubusercontent.com/u/25914066?v=4" width="100px;" alt="Mark Skelton"/><br /><sub><b>Mark Skelton</b></sub></a><br /><a href="#design-mskelton" title="Design">🎨</a></td>
|
||||
<td align="center"><a href="https://github.com/drod3763"><img src="https://avatars2.githubusercontent.com/u/7785716?v=4" width="100px;" alt="Derick Rodriguez"/><br /><sub><b>Derick Rodriguez</b></sub></a><br /><a href="https://github.com/kiliman/operator-mono-lig/commits?author=drod3763" title="Documentation">📖</a></td>
|
||||
<td align="center"><a href="https://github.com/amitkparekh"><img src="https://avatars3.githubusercontent.com/u/7276308?v=4" width="100px;" alt="Amit Parekh"/><br /><sub><b>Amit Parekh</b></sub></a><br /><a href="https://github.com/kiliman/operator-mono-lig/commits?author=amitkparekh" title="Documentation">📖</a> <a href="#design-amitkparekh" title="Design">🎨</a></td>
|
||||
<td align="center"><a href="https://github.com/kiliman"><img src="https://avatars3.githubusercontent.com/u/47168?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Kiliman</b></sub></a><br /><a href="https://github.com/kiliman/operator-mono-lig/commits?author=kiliman" title="Code">💻</a> <a href="https://github.com/kiliman/operator-mono-lig/commits?author=kiliman" title="Documentation">📖</a> <a href="#design-kiliman" title="Design">🎨</a></td>
|
||||
<td align="center"><a href="https://github.com/mskelton"><img src="https://avatars3.githubusercontent.com/u/25914066?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Mark Skelton</b></sub></a><br /><a href="#design-mskelton" title="Design">🎨</a></td>
|
||||
<td align="center"><a href="https://github.com/drod3763"><img src="https://avatars2.githubusercontent.com/u/7785716?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Derick Rodriguez</b></sub></a><br /><a href="https://github.com/kiliman/operator-mono-lig/commits?author=drod3763" title="Documentation">📖</a></td>
|
||||
<td align="center"><a href="https://github.com/amitkparekh"><img src="https://avatars3.githubusercontent.com/u/7276308?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Amit Parekh</b></sub></a><br /><a href="https://github.com/kiliman/operator-mono-lig/commits?author=amitkparekh" title="Documentation">📖</a> <a href="#design-amitkparekh" title="Design">🎨</a></td>
|
||||
<td align="center"><a href="https://github.com/CandySunPlus"><img src="https://avatars0.githubusercontent.com/u/502700?v=4?s=100" width="100px;" alt=""/><br /><sub><b>NikSun</b></sub></a><br /><a href="#design-CandySunPlus" title="Design">🎨</a></td>
|
||||
<td align="center"><a href="https://github.com/Jakob6174"><img src="https://avatars3.githubusercontent.com/u/40262817?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Jakob Pearson</b></sub></a><br /><a href="https://github.com/kiliman/operator-mono-lig/commits?author=Jakob6174" title="Code">💻</a></td>
|
||||
<td align="center"><a href="http://killua.me/"><img src="https://avatars.githubusercontent.com/u/457822?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Luigi</b></sub></a><br /><a href="https://github.com/kiliman/operator-mono-lig/commits?author=killua99" title="Documentation">📖</a></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="center"><a href="https://github.com/GlorifiedBicycle"><img src="https://avatars.githubusercontent.com/u/71753585?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Reland Boyle</b></sub></a><br /><a href="https://github.com/kiliman/operator-mono-lig/commits?author=GlorifiedBicycle" title="Documentation">📖</a></td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
<!-- markdownlint-enable -->
|
||||
<!-- markdownlint-restore -->
|
||||
<!-- prettier-ignore-end -->
|
||||
|
||||
<!-- ALL-CONTRIBUTORS-LIST:END -->
|
||||
|
||||
This project follows the [all-contributors](https://github.com/all-contributors/all-contributors) specification. Contributions of any kind welcome!
|
||||
|
||||
@@ -3,19 +3,25 @@ setlocal
|
||||
|
||||
if not exist .\build\* mkdir build
|
||||
|
||||
set flags=
|
||||
if "%1"=="--italics-hack-off" (
|
||||
set flags=%1
|
||||
shift
|
||||
)
|
||||
rem only build passed in font
|
||||
if not "%1%"=="" (
|
||||
call :build_font %1
|
||||
if not "%1"=="" (
|
||||
call :build_font %1 %flags%
|
||||
exit /b
|
||||
)
|
||||
|
||||
rem build all fonts
|
||||
for /d %%d in (.\ligature\*) do call :build_font %%~nd
|
||||
for /d %%d in (.\ligature\*) do call :build_font %%~nd %flags%
|
||||
exit /b
|
||||
|
||||
|
||||
:build_font
|
||||
set lig=%1
|
||||
set flags=%2
|
||||
set otf=%lig:Lig-=-%
|
||||
|
||||
if not exist .\original\%otf%.otf exit /b
|
||||
@@ -23,6 +29,15 @@ if not exist .\ligature\%lig%\glyphs\* exit /b
|
||||
|
||||
@echo Building %lig%
|
||||
ttx -f .\original\%otf%.otf
|
||||
node index.js %otf%
|
||||
node index.js %otf% %flags%
|
||||
ttx -f .\build\%lig%.ttx
|
||||
rem check if "SSm" is in name since the features are slightly different
|
||||
@echo.%lig% | findstr /C:"SSm" 1>nul
|
||||
if errorlevel 1 (
|
||||
set fea=".\features\default.fea"
|
||||
) else (
|
||||
set fea=".\features\defaultSSm.fea"
|
||||
)
|
||||
fonttools feaLib -v -o ".\build\%lig%.otf" %fea% ".\build\%lig%.otf"
|
||||
|
||||
exit /b
|
||||
|
||||
@@ -4,6 +4,7 @@ mkdir -p build
|
||||
|
||||
build_font() {
|
||||
lig="$1"
|
||||
flags="$2"
|
||||
otf=${lig/Lig-/-}
|
||||
|
||||
if [ ! -e "./original/$otf.otf" ]
|
||||
@@ -15,19 +16,32 @@ build_font() {
|
||||
return
|
||||
fi
|
||||
|
||||
echo Building $1
|
||||
echo Building "$1"
|
||||
ttx -f "./original/$otf.otf"
|
||||
node index.js $otf
|
||||
ttx -f ./build/$1.ttx
|
||||
node index.js "$otf" "$flags"
|
||||
|
||||
ttx -f "./build/$1.ttx"
|
||||
if [[ $lig == *"SSm"* ]]; then
|
||||
fea="./features/defaultSSm.fea"
|
||||
else
|
||||
fea="./features/default.fea"
|
||||
fi
|
||||
fonttools feaLib -v -o "./build/$1.otf" $fea "./build/$1.otf"
|
||||
}
|
||||
|
||||
flags=
|
||||
if [ "$1" = "--italics-hack-off" ]
|
||||
then
|
||||
flags=$1
|
||||
shift
|
||||
fi
|
||||
if [ -n "$1" ]
|
||||
then
|
||||
# build specified font
|
||||
build_font $1
|
||||
build_font "$1" "$flags"
|
||||
else
|
||||
# build all available fonts
|
||||
for d in ./ligature/*/ ; do
|
||||
build_font $(basename $d)
|
||||
build_font "$(basename "$d")" "$flags"
|
||||
done
|
||||
fi
|
||||
|
||||
@@ -0,0 +1,65 @@
|
||||
const fs = require('fs')
|
||||
|
||||
const rules = [
|
||||
'',
|
||||
`
|
||||
lookup 1 {
|
||||
sub 1 by glyph;
|
||||
} 1;`,
|
||||
`
|
||||
lookup 1_2 {
|
||||
ignore sub 1 1' 2;
|
||||
ignore sub 1' 2 2;
|
||||
sub 1.spacer 2' by glyph;
|
||||
sub 1' 2 by 1.spacer;
|
||||
} 1_2;`,
|
||||
`
|
||||
lookup 1_2_3 {
|
||||
ignore sub 1 1' 2 3;
|
||||
ignore sub 1' 2 3 3;
|
||||
sub 1.spacer 2.spacer 3' by glyph;
|
||||
sub 1.spacer 2' 3 by 2.spacer;
|
||||
sub 1' 2 3 by 1.spacer;
|
||||
} 1_2_3;`,
|
||||
`
|
||||
lookup 1_2_3_4 {
|
||||
ignore sub 1 1' 2 3 4;
|
||||
ignore sub 1' 2 3 4 4;
|
||||
sub 1.spacer 2.spacer 3.spacer 4' by glyph;
|
||||
sub 1.spacer 2.spacer 3' 4 by 3.spacer;
|
||||
sub 1.spacer 2' 3 4 by 2.spacer;
|
||||
sub 1' 2 3 4 by 1.spacer;
|
||||
} 1_2_3_4;`,
|
||||
]
|
||||
|
||||
const gencalt = ligatures => {
|
||||
let calt = 'feature calt {\n'
|
||||
const ligs = {}
|
||||
|
||||
ligatures
|
||||
.filter(l => !!l.name.match(/\.liga$/) || l.name !== l.glyph)
|
||||
.map(l => l.glyph)
|
||||
.sort((a, b) => {
|
||||
const length = b.split('_').length - a.split('_').length
|
||||
if (length !== 0) return length
|
||||
return a < b ? -1 : 1
|
||||
})
|
||||
.forEach(g => {
|
||||
g.split('.')
|
||||
.slice(0, 1)
|
||||
.forEach(l => {
|
||||
if (ligs[l]) return
|
||||
ligs[l] = true
|
||||
const c = l.split('_')
|
||||
let rule = rules[c.length]
|
||||
rule = rule
|
||||
.replace(/\d/g, m => c[parseInt(m) - 1])
|
||||
.replace(/glyph/g, g)
|
||||
calt += rule + '\n'
|
||||
})
|
||||
})
|
||||
|
||||
return calt + '\n} calt;\n'
|
||||
}
|
||||
|
||||
exports.gencalt = gencalt
|
||||
|
After Width: | Height: | Size: 81 KiB |
|
After Width: | Height: | Size: 81 KiB |
|
After Width: | Height: | Size: 22 KiB |
|
After Width: | Height: | Size: 273 KiB |
|
After Width: | Height: | Size: 321 KiB |
|
After Width: | Height: | Size: 27 KiB |
|
After Width: | Height: | Size: 329 KiB |
|
After Width: | Height: | Size: 378 KiB |
|
After Width: | Height: | Size: 157 KiB |
|
After Width: | Height: | Size: 203 KiB |
|
After Width: | Height: | Size: 86 KiB |
|
After Width: | Height: | Size: 22 KiB |
|
After Width: | Height: | Size: 218 KiB |
|
After Width: | Height: | Size: 175 KiB |
|
After Width: | Height: | Size: 175 KiB |
|
After Width: | Height: | Size: 33 KiB |
|
After Width: | Height: | Size: 33 KiB |
@@ -0,0 +1,4 @@
|
||||
# Introduction
|
||||
|
||||
Testing
|
||||
|
||||
@@ -0,0 +1,19 @@
|
||||
# Table of contents
|
||||
|
||||
* [Introduction](README.md)
|
||||
* [Installation instructions](installation-instructions.md)
|
||||
* [Changelog](changelog.md)
|
||||
|
||||
## Developing ligatures
|
||||
|
||||
* [Setting up your development environment](developing-ligatures/setting-up-your-development-environment.md)
|
||||
* [Designing your first ligature](developing-ligatures/designing-your-first-ligature.md)
|
||||
* [Committing your Glyphs file](developing-ligatures/committing-your-glyphs-file.md)
|
||||
* [Ensuring ligatures work at small sizes](developing-ligatures/ensuring-ligatures-work-at-small-sizes.md)
|
||||
|
||||
## Ligature Recipes
|
||||
|
||||
* [www](ligature-recipes/www.md)
|
||||
* [Double-braces](ligature-recipes/double-braces/README.md)
|
||||
* [Roman variant](ligature-recipes/double-braces/roman-variant.md)
|
||||
|
||||
@@ -0,0 +1,26 @@
|
||||
---
|
||||
description: See what has changed each release.
|
||||
---
|
||||
|
||||
# Changelog
|
||||
|
||||
###
|
||||
|
||||
## 15.0.0 - 2042-12-0
|
||||
|
||||
### Fixed
|
||||
|
||||
* Removed humans, they weren't doing fine with animals.
|
||||
|
||||
### Changed
|
||||
|
||||
* Animals are now super cute, all of them.
|
||||
|
||||
## 14.0.0 - 2042-10-06
|
||||
|
||||
### Added
|
||||
|
||||
* Introduced animals into the world, we believe they're going to be a neat addition.
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,21 @@
|
||||
# Committing your Glyphs file
|
||||
|
||||
The Glyphs file is very difficult to merge, so standard tools like `git rebase` don't work well. I have created some tools that will allow you to update your existing Glyphs file on top of the current.
|
||||
|
||||
{% hint style="warning" %}
|
||||
Make sure you have created a separate branch for your changes and you've committed all your changes to the branch.
|
||||
{% endhint %}
|
||||
|
||||
1. When you're ready to issue a PR for your changes, you need to run the `./tools/glyphysrebase.sh` tool.
|
||||
2. You can now create your PR, or continue making changes and running the rebase tool periodically to keep up-to-date with master.
|
||||
|
||||
## How the tool works
|
||||
|
||||
1. Checks out a clean copy of `master` in a temporary folder.
|
||||
2. Copies your current working copy to a backup folder.
|
||||
3. Copies the master copy into your working copy \(basically resetting everything back before your changes\).
|
||||
4. Runs the `./tools/copyallglyphs.sh` script to copy ligatures from your backup folder to the current master in your working copy.
|
||||
5. At this point, you now have a glyphs file that includes your custom ligatures on top of the current master.
|
||||
6. The "rebased" files are then committed.
|
||||
7. You can now issue a PR. This should easily merge into master.
|
||||
|
||||
@@ -0,0 +1,23 @@
|
||||
# Designing your first ligature
|
||||
|
||||
## Getting Super Powers
|
||||
|
||||
Becoming a super hero is a fairly straight forward process:
|
||||
|
||||
```
|
||||
$ give me super-powers
|
||||
```
|
||||
|
||||
{% hint style="info" %}
|
||||
Super-powers are granted randomly so please submit an issue if you're not happy with yours.
|
||||
{% endhint %}
|
||||
|
||||
Once you're strong enough, save the world:
|
||||
|
||||
```
|
||||
// Ain't no code for that yet, sorry
|
||||
echo 'You got to trust me on this, I saved the world'
|
||||
```
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,6 @@
|
||||
# Ensuring ligatures work at small sizes
|
||||
|
||||
After creating each ligature, you going to need to make sure it works at very small sizes. Ensure the brace works at very small sizes by looking at it when its very small, by dragging up from the bottom of the editor. This need to be done because as [ScreenSmart fonts are guaranteed to work at a minimum of 9px](https://www.typography.com/fonts/operator/how-to-use#setting_text_and_headlines):
|
||||
|
||||

|
||||
|
||||
@@ -0,0 +1,27 @@
|
||||
---
|
||||
description: Things you will need to create additional ligatures.
|
||||
---
|
||||
|
||||
# Setting up your development environment
|
||||
|
||||
## Getting Super Powers
|
||||
|
||||
Becoming a super hero is a fairly straight forward process:
|
||||
|
||||
```
|
||||
$ give me super-powers
|
||||
```
|
||||
|
||||
{% hint style="info" %}
|
||||
Super-powers are granted randomly so please submit an issue if you're not happy with yours.
|
||||
{% endhint %}
|
||||
|
||||
Once you're strong enough, save the world:
|
||||
|
||||
```
|
||||
// Ain't no code for that yet, sorry
|
||||
echo 'You got to trust me on this, I saved the world'
|
||||
```
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,6 @@
|
||||
---
|
||||
description: How to install the ligatures
|
||||
---
|
||||
|
||||
# Installation instructions
|
||||
|
||||
@@ -0,0 +1,43 @@
|
||||
---
|
||||
description: Recipe for the double-brace ligature
|
||||
---
|
||||
|
||||
# Double-braces
|
||||
|
||||
## Creating the ligature \(Roman\)
|
||||
|
||||
1.
|
||||

|
||||
|
||||
For whichever brace is the "inner-brace", change the dimensions as so, changing only the size \(the `%` in the middle column\) and the rotation \(the right most setting\):
|
||||
|
||||

|
||||
|
||||
Move the left-most brace to the left and the right-most brace to the left so the top/bottom parts cross the middle guide and the numbers are like so:
|
||||
|
||||

|
||||
|
||||
Create a new guide and move the guide so it intersects the pointy inner-corner of the larger brace
|
||||
|
||||

|
||||
|
||||
Move the smaller brace vertically \(up/down\) so the two pointy inner-corner bits cross like so:
|
||||
|
||||

|
||||
|
||||
## Creating the italic ligature
|
||||
|
||||
Repeat all the steps as above ligature above **BUT set the middle guide** **to**:
|
||||
|
||||

|
||||
|
||||
## Final ligatures
|
||||
|
||||

|
||||
|
||||

|
||||
|
||||

|
||||
|
||||

|
||||
|
||||
@@ -0,0 +1,14 @@
|
||||
---
|
||||
description: How to create the Roman variant of the double-brace ligature
|
||||
---
|
||||
|
||||
# Roman variant
|
||||
|
||||
{% hint style="info" %}
|
||||
|
||||
{% endhint %}
|
||||
|
||||
1. Add the `braceleft` component twice, or `braceright` component twice.
|
||||
2. Create a guide \(Right-click -> Add Guide\)
|
||||
3. Set the settings on the guide as so:
|
||||
|
||||
@@ -0,0 +1,2 @@
|
||||
# www
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
calt.fea
|
||||
@@ -0,0 +1,234 @@
|
||||
##############################
|
||||
# Languagesystem definitions #
|
||||
##############################
|
||||
languagesystem DFLT dflt; # Default default
|
||||
languagesystem latn dflt; # Latin default
|
||||
languagesystem latn CAT ; # Latin Catalan
|
||||
##########
|
||||
# Prefix #
|
||||
##########
|
||||
@HexDigit = [a b c d e f A B C D E F];
|
||||
@Digit = [zero one two three four five six seven eight nine];
|
||||
@DigitAll = [zero one two three four five six seven eight nine zero.num one.num two.num three.num four.num five.num six.num seven.num eight.num nine.num zero.den one.den two.den three.den four.den five.den six.den seven.den eight.den nine.den];
|
||||
@DigitSmall = [zero.small one.small two.small three.small four.small five.small six.small seven.small eight.small nine.small];
|
||||
@DigitNumerator = [zero.num one.num two.num three four.num five.num six.num seven.num eight.num nine.num];
|
||||
@DigitDenominator = [zero.den one.den two.den three.den four.den five.den six.den seven.den eight.den nine.den];
|
||||
@DigitSuperior = [zero.sup one.sup two.sup three.sup four.sup five.sup six.sup seven.sup eight.sup nine.sup];
|
||||
@DigitInferior = [zero.inf one.inf two.inf three.inf four.inf five.inf six.inf seven.inf eight.inf nine.inf];
|
||||
#######################
|
||||
# Feature definitions #
|
||||
#######################
|
||||
feature locl {
|
||||
# GSUB feature: Localized Forms
|
||||
script latn; # Latin
|
||||
language CAT; # Catalan
|
||||
sub l' periodcentered' by ldot;
|
||||
sub L' periodcentered' by Ldot;
|
||||
} locl;
|
||||
|
||||
feature aalt useExtension {
|
||||
# GSUB feature: Access All Alternates
|
||||
feature case;
|
||||
feature dnom;
|
||||
feature numr;
|
||||
feature salt;
|
||||
feature sinf;
|
||||
feature ss01;
|
||||
feature ss03;
|
||||
feature ss04;
|
||||
feature ss05;
|
||||
feature ss07;
|
||||
feature ss08;
|
||||
feature ss09;
|
||||
feature ss10;
|
||||
feature subs;
|
||||
feature sups;
|
||||
feature smcp;
|
||||
feature c2sc;
|
||||
} aalt;
|
||||
|
||||
feature frac {
|
||||
# GSUB feature: Fractions
|
||||
lookup frac0 {
|
||||
sub @Digit slash' @Digit by fraction;
|
||||
} frac0;
|
||||
|
||||
lookup frac1 {
|
||||
ignore sub @DigitAll @DigitAll fraction';
|
||||
ignore sub fraction' @DigitAll @DigitAll;
|
||||
sub @DigitAll fraction' @DigitAll by fraction.afrc;
|
||||
} frac1;
|
||||
|
||||
lookup frac2 {
|
||||
sub @Digit' fraction.afrc by @DigitNumerator;
|
||||
sub fraction.afrc @Digit' by @DigitDenominator;
|
||||
} frac2;
|
||||
|
||||
lookup frac3 {
|
||||
sub one.num fraction.afrc two.den by onehalf;
|
||||
sub one.num fraction.afrc three.den by onethird;
|
||||
sub one.num fraction.afrc four.den by onequarter;
|
||||
sub one.num fraction.afrc five.den by onefifth;
|
||||
sub one.num fraction.afrc six.den by onesixth;
|
||||
sub one.num fraction.afrc eight.den by oneeighth;
|
||||
sub two.num fraction.afrc three.den by twothirds;
|
||||
sub two.num fraction.afrc five.den by twofifths;
|
||||
sub three.num fraction.afrc four.den by threequarters;
|
||||
sub three.num fraction.afrc five.den by threefifths;
|
||||
sub three.num fraction.afrc eight.den by threeeighths;
|
||||
sub four.num fraction.afrc five.den by fourfifths;
|
||||
sub five.num fraction.afrc six.den by fivesixths;
|
||||
sub five.num fraction.afrc eight.den by fiveeighths;
|
||||
sub seven.num fraction.afrc eight.den by seveneighths;
|
||||
} frac3;
|
||||
} frac;
|
||||
|
||||
feature numr {
|
||||
# GSUB feature: Numerators
|
||||
sub @Digit by @DigitNumerator;
|
||||
} numr;
|
||||
|
||||
feature dnom {
|
||||
# GSUB feature: Denominators
|
||||
sub @Digit by @DigitDenominator;
|
||||
} dnom;
|
||||
|
||||
feature sups {
|
||||
# GSUB feature: Superscript
|
||||
sub @Digit by @DigitSuperior;
|
||||
} sups;
|
||||
|
||||
feature subs {
|
||||
# GSUB feature: Subscript
|
||||
sub @Digit by @DigitInferior;
|
||||
} subs;
|
||||
|
||||
feature sinf {
|
||||
# GSUB feature: Scientific Inferiors
|
||||
sub @Digit by @DigitInferior;
|
||||
} sinf;
|
||||
|
||||
feature ordn {
|
||||
# Ordinals
|
||||
sub @Digit [A a]' by ordfeminine;
|
||||
sub @Digit [O o]' by ordmasculine;
|
||||
sub N o period by numero;
|
||||
} ordn;
|
||||
|
||||
feature smcp {
|
||||
# Small Caps
|
||||
sub @Digit by @DigitSmall;
|
||||
} smcp;
|
||||
|
||||
feature c2sc {
|
||||
# Capitals to Small Caps
|
||||
sub @Digit by @DigitSmall;
|
||||
} c2sc;
|
||||
|
||||
feature case {
|
||||
# GSUB feature: Case-Sensitive Forms
|
||||
sub guillemotleft by guillemotleft.cap;
|
||||
sub guillemotright by guillemotright.cap;
|
||||
sub guilsinglleft by guilsinglleft.cap;
|
||||
sub guilsinglright by guilsinglright.cap;
|
||||
sub parenleft by parenleft.cap;
|
||||
sub parenright by parenright.cap;
|
||||
sub bracketleft by bracketleft.cap;
|
||||
sub bracketright by bracketright.cap;
|
||||
sub braceleft by braceleft.cap;
|
||||
sub braceright by braceright.cap;
|
||||
} case;
|
||||
|
||||
|
||||
|
||||
include(calt.fea);
|
||||
|
||||
|
||||
|
||||
feature salt {
|
||||
# GSUB feature: Stylistic Alternates
|
||||
sub registered by registered.alt;
|
||||
sub colon by colon.alt;
|
||||
sub bullet by bullet.alt;
|
||||
sub asterisk by asterisk.alt;
|
||||
sub zero by zero.alt;
|
||||
sub underscore by underscore.alt;
|
||||
lookup salt {
|
||||
# GSUB lookup 20, type 16 (Chaining Context)
|
||||
sub @DigitAll slash' @DigitAll by fraction;
|
||||
} salt;
|
||||
} salt;
|
||||
|
||||
feature ss01 {
|
||||
featureNames {
|
||||
name "Large Registered Symbol";
|
||||
};
|
||||
sub registered by registered.alt;
|
||||
} ss01;
|
||||
|
||||
feature ss03 {
|
||||
featureNames {
|
||||
name "Raised Colon";
|
||||
};
|
||||
sub colon by colon.alt;
|
||||
} ss03;
|
||||
|
||||
feature ss04 {
|
||||
featureNames {
|
||||
name "Square Bullet";
|
||||
};
|
||||
sub bullet by bullet.alt;
|
||||
} ss04;
|
||||
|
||||
feature ss05 {
|
||||
featureNames {
|
||||
name "Six-Pointed Asterisk";
|
||||
};
|
||||
sub asterisk by asterisk.alt;
|
||||
} ss05;
|
||||
|
||||
feature ss07 {
|
||||
featureNames {
|
||||
name "Unslashed Zero";
|
||||
};
|
||||
sub zero by zero.alt;
|
||||
} ss07;
|
||||
|
||||
feature ss08 {
|
||||
featureNames {
|
||||
name "Connected Underscore";
|
||||
};
|
||||
sub underscore by underscore.alt;
|
||||
} ss08;
|
||||
|
||||
feature ss09 {
|
||||
featureNames {
|
||||
name "Fraction Bar";
|
||||
};
|
||||
sub @DigitAll slash' @DigitAll by fraction;
|
||||
} ss09;
|
||||
|
||||
feature ss10 {
|
||||
featureNames {
|
||||
name "Hexidecimal Multiply Sign";
|
||||
};
|
||||
### 0xFF
|
||||
sub [zero zero.alt] x' [@Digit @HexDigit] by multiply;
|
||||
### 800x600
|
||||
sub [@Digit zero.alt] x' [@Digit zero.alt] by multiply;
|
||||
} ss10;
|
||||
|
||||
feature rupa {
|
||||
sub R p by R_p;
|
||||
} rupa;
|
||||
|
||||
feature kern {
|
||||
# GPOS feature: Kerning
|
||||
lookup kern {
|
||||
# GPOS lookup 1, type 2 (Pair adjustment)
|
||||
pos fraction.afrc @DigitDenominator -550;
|
||||
pos @DigitNumerator fraction.afrc -550;
|
||||
} kern;
|
||||
} kern;
|
||||
|
||||
|
||||
@@ -0,0 +1,252 @@
|
||||
##############################
|
||||
# Languagesystem definitions #
|
||||
##############################
|
||||
languagesystem DFLT dflt; # Default default
|
||||
languagesystem latn dflt; # Latin default
|
||||
languagesystem latn CAT ; # Latin Catalan
|
||||
##########
|
||||
# Prefix #
|
||||
##########
|
||||
@HexDigit = [a b c d e f A B C D E F];
|
||||
@Digit = [zero one two three four five six seven eight nine];
|
||||
@DigitAll = [zero one two three four five six seven eight nine zero.num one.num two.num three.num four.num five.num six.num seven.num eight.num nine.num zero.den one.den two.den three.den four.den five.den six.den seven.den eight.den nine.den];
|
||||
@DigitSmall = [zero.small one.small two.small three.small four.small five.small six.small seven.small eight.small nine.small];
|
||||
@DigitNumerator = [zero.num one.num two.num three four.num five.num six.num seven.num eight.num nine.num];
|
||||
@DigitDenominator = [zero.den one.den two.den three.den four.den five.den six.den seven.den eight.den nine.den];
|
||||
@DigitSuperior = [zero.sup one.sup two.sup three.sup four.sup five.sup six.sup seven.sup eight.sup nine.sup];
|
||||
@DigitInferior = [zero.inf one.inf two.inf three.inf four.inf five.inf six.inf seven.inf eight.inf nine.inf];
|
||||
#######################
|
||||
# Feature definitions #
|
||||
#######################
|
||||
feature locl {
|
||||
# GSUB feature: Localized Forms
|
||||
script latn; # Latin
|
||||
language CAT; # Catalan
|
||||
sub l' periodcentered' by ldot;
|
||||
sub L' periodcentered' by Ldot;
|
||||
} locl;
|
||||
|
||||
feature aalt useExtension {
|
||||
# GSUB feature: Access All Alternates
|
||||
feature case;
|
||||
feature dnom;
|
||||
feature numr;
|
||||
feature salt;
|
||||
feature sinf;
|
||||
feature ss01;
|
||||
feature ss03;
|
||||
feature ss04;
|
||||
feature ss05;
|
||||
feature ss07;
|
||||
feature ss08;
|
||||
feature ss09;
|
||||
feature ss10;
|
||||
feature ss11;
|
||||
feature ss12;
|
||||
feature subs;
|
||||
feature sups;
|
||||
feature smcp;
|
||||
feature c2sc;
|
||||
} aalt;
|
||||
|
||||
feature frac {
|
||||
# GSUB feature: Fractions
|
||||
lookup frac0 {
|
||||
sub @Digit slash' @Digit by fraction;
|
||||
} frac0;
|
||||
|
||||
lookup frac1 {
|
||||
ignore sub @DigitAll @DigitAll fraction';
|
||||
ignore sub fraction' @DigitAll @DigitAll;
|
||||
sub @DigitAll fraction' @DigitAll by fraction.afrc;
|
||||
} frac1;
|
||||
|
||||
lookup frac2 {
|
||||
sub @Digit' fraction.afrc by @DigitNumerator;
|
||||
sub fraction.afrc @Digit' by @DigitDenominator;
|
||||
} frac2;
|
||||
|
||||
lookup frac3 {
|
||||
sub one.num fraction.afrc two.den by onehalf;
|
||||
sub one.num fraction.afrc three.den by onethird;
|
||||
sub one.num fraction.afrc four.den by onequarter;
|
||||
sub one.num fraction.afrc five.den by onefifth;
|
||||
sub one.num fraction.afrc six.den by onesixth;
|
||||
sub one.num fraction.afrc eight.den by oneeighth;
|
||||
sub two.num fraction.afrc three.den by twothirds;
|
||||
sub two.num fraction.afrc five.den by twofifths;
|
||||
sub three.num fraction.afrc four.den by threequarters;
|
||||
sub three.num fraction.afrc five.den by threefifths;
|
||||
sub three.num fraction.afrc eight.den by threeeighths;
|
||||
sub four.num fraction.afrc five.den by fourfifths;
|
||||
sub five.num fraction.afrc six.den by fivesixths;
|
||||
sub five.num fraction.afrc eight.den by fiveeighths;
|
||||
sub seven.num fraction.afrc eight.den by seveneighths;
|
||||
} frac3;
|
||||
} frac;
|
||||
|
||||
feature numr {
|
||||
# GSUB feature: Numerators
|
||||
sub @Digit by @DigitNumerator;
|
||||
} numr;
|
||||
|
||||
feature dnom {
|
||||
# GSUB feature: Denominators
|
||||
sub @Digit by @DigitDenominator;
|
||||
} dnom;
|
||||
|
||||
feature sups {
|
||||
# GSUB feature: Superscript
|
||||
sub @Digit by @DigitSuperior;
|
||||
} sups;
|
||||
|
||||
feature subs {
|
||||
# GSUB feature: Subscript
|
||||
sub @Digit by @DigitInferior;
|
||||
} subs;
|
||||
|
||||
feature sinf {
|
||||
# GSUB feature: Scientific Inferiors
|
||||
sub @Digit by @DigitInferior;
|
||||
} sinf;
|
||||
|
||||
feature ordn {
|
||||
# Ordinals
|
||||
sub @Digit [A a]' by ordfeminine;
|
||||
sub @Digit [O o]' by ordmasculine;
|
||||
sub N o period by numero;
|
||||
} ordn;
|
||||
|
||||
feature smcp {
|
||||
# Small Caps
|
||||
sub @Digit by @DigitSmall;
|
||||
} smcp;
|
||||
|
||||
feature c2sc {
|
||||
# Capitals to Small Caps
|
||||
sub @Digit by @DigitSmall;
|
||||
} c2sc;
|
||||
|
||||
feature case {
|
||||
# GSUB feature: Case-Sensitive Forms
|
||||
sub guillemotleft by guillemotleft.cap;
|
||||
sub guillemotright by guillemotright.cap;
|
||||
sub guilsinglleft by guilsinglleft.cap;
|
||||
sub guilsinglright by guilsinglright.cap;
|
||||
sub parenleft by parenleft.cap;
|
||||
sub parenright by parenright.cap;
|
||||
sub bracketleft by bracketleft.cap;
|
||||
sub bracketright by bracketright.cap;
|
||||
sub braceleft by braceleft.cap;
|
||||
sub braceright by braceright.cap;
|
||||
} case;
|
||||
|
||||
|
||||
|
||||
include(calt.fea);
|
||||
|
||||
|
||||
|
||||
feature salt {
|
||||
# GSUB feature: Stylistic Alternates
|
||||
sub registered by registered.alt;
|
||||
sub colon by colon.alt;
|
||||
sub bullet by bullet.alt;
|
||||
sub asterisk by asterisk.alt;
|
||||
sub zero by zero.alt;
|
||||
sub underscore by underscore.alt;
|
||||
lookup salt {
|
||||
# GSUB lookup 20, type 16 (Chaining Context)
|
||||
sub @DigitAll slash' @DigitAll by fraction;
|
||||
} salt;
|
||||
} salt;
|
||||
|
||||
feature ss01 {
|
||||
featureNames {
|
||||
name "Large Registered Symbol";
|
||||
};
|
||||
sub registered by registered.alt;
|
||||
} ss01;
|
||||
|
||||
feature ss03 {
|
||||
featureNames {
|
||||
name "Raised Colon";
|
||||
};
|
||||
sub colon by colon.alt;
|
||||
} ss03;
|
||||
|
||||
feature ss04 {
|
||||
featureNames {
|
||||
name "Square Bullet";
|
||||
};
|
||||
sub bullet by bullet.alt;
|
||||
} ss04;
|
||||
|
||||
feature ss05 {
|
||||
featureNames {
|
||||
name "Six-Pointed Asterisk";
|
||||
};
|
||||
sub asterisk by asterisk.alt;
|
||||
} ss05;
|
||||
|
||||
feature ss07 {
|
||||
featureNames {
|
||||
name "Unslashed Zero";
|
||||
};
|
||||
sub zero by zero.alt;
|
||||
} ss07;
|
||||
|
||||
feature ss08 {
|
||||
featureNames {
|
||||
name "Connected Underscore";
|
||||
};
|
||||
sub underscore by underscore.alt;
|
||||
} ss08;
|
||||
|
||||
feature ss09 {
|
||||
featureNames {
|
||||
name "Fraction Bar";
|
||||
};
|
||||
sub @DigitAll slash' @DigitAll by fraction;
|
||||
} ss09;
|
||||
|
||||
feature ss10 {
|
||||
featureNames {
|
||||
name "Hexidecimal Multiply Sign";
|
||||
};
|
||||
### 0xFF
|
||||
sub [zero zero.alt] x' [@Digit @HexDigit] by multiply;
|
||||
### 800x600
|
||||
sub [@Digit zero.alt] x' [@Digit zero.alt] by multiply;
|
||||
} ss10;
|
||||
|
||||
feature ss11 {
|
||||
featureNames {
|
||||
name "Equality Spaces";
|
||||
};
|
||||
sub equal_equal.liga by equal_equal.liga.ss11;
|
||||
sub equal_equal_equal.liga by equal_equal_equal.liga.ss11;
|
||||
} ss11;
|
||||
|
||||
feature ss12 {
|
||||
featureNames {
|
||||
name "Less-than/Greater-than Horizontal Bar";
|
||||
};
|
||||
sub less_equal.liga by less_equal.liga.ss12;
|
||||
sub greater_equal.liga by greater_equal.liga.ss12;
|
||||
} ss12;
|
||||
|
||||
feature rupa {
|
||||
sub R p by R_p;
|
||||
} rupa;
|
||||
|
||||
feature kern {
|
||||
# GPOS feature: Kerning
|
||||
lookup kern {
|
||||
# GPOS lookup 1, type 2 (Pair adjustment)
|
||||
pos fraction.afrc @DigitDenominator -625;
|
||||
pos @DigitNumerator fraction.afrc -625;
|
||||
} kern;
|
||||
} kern;
|
||||
|
||||
|
||||
@@ -0,0 +1,85 @@
|
||||
const fs = require('fs')
|
||||
const { createCanvas } = require('canvas')
|
||||
|
||||
const width = 64
|
||||
const height = 48
|
||||
const weight = 300
|
||||
|
||||
const map = {
|
||||
ampersand: '&',
|
||||
bar: '|',
|
||||
colon: ':',
|
||||
equal: '=',
|
||||
exclam: '!',
|
||||
greater: '>',
|
||||
hyphen: '-',
|
||||
less: '<',
|
||||
plus: '+',
|
||||
question: '?',
|
||||
slash: '/',
|
||||
underscore: '_',
|
||||
w: 'w',
|
||||
}
|
||||
|
||||
function generateLigaturePreview(style, filename) {
|
||||
const ligature = filename.split('.').slice(0, 1)[0]
|
||||
const chars = ligature.split('_')
|
||||
|
||||
const text = chars.reduce((t, c) => t + map[c], '')
|
||||
|
||||
const canvas = createCanvas(width, height)
|
||||
const context = canvas.getContext('2d')
|
||||
|
||||
context.fillStyle = '#000'
|
||||
context.fillRect(0, 0, width, height)
|
||||
|
||||
context.font = `${weight} ${style} 18pt "Operator Mono SSm Lig"`
|
||||
context.textAlign = 'center'
|
||||
context.fillStyle = '#fff'
|
||||
context.text = text
|
||||
context.fillText(text, 32, 32)
|
||||
|
||||
const buffer = canvas.toBuffer('image/png')
|
||||
console.log(ligature)
|
||||
fs.writeFileSync(`./images/preview/${style}/${ligature}.png`, buffer)
|
||||
|
||||
return { text, ligature, filename: `${ligature}.png` }
|
||||
}
|
||||
|
||||
function generate(style, filenames) {
|
||||
let html = `<html><head>
|
||||
<style>
|
||||
body { background-color: #000; color: #fff; font-family: sans-serif; margin: 16px;}
|
||||
a { color: #fff; text-decoration: none; padding: 4px;}
|
||||
a.active {color: #000; background-color: #fff;}
|
||||
.container { display: grid; grid-template-columns: repeat(auto-fill, minmax(200px, 1fr)); }
|
||||
.ligature { display: flex; flex-direction: column; align-items: center; margin: 8px; }
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<h1>Operator Mono Ligatures</h1>
|
||||
<a href="https://htmlpreview.github.io/?https://github.com/kiliman/operator-mono-lig/blob/master/images/preview/normal/index.html" class="${
|
||||
style === 'normal' ? 'active' : ''
|
||||
}">Normal</a> |
|
||||
<a href="https://htmlpreview.github.io/?https://github.com/kiliman/operator-mono-lig/blob/master/images/preview/italic/index.html" class="${
|
||||
style === 'italic' ? 'active' : ''
|
||||
}">Italic</a>
|
||||
<div class="container">
|
||||
`
|
||||
|
||||
filenames.forEach(f => {
|
||||
const { ligature, filename } = generateLigaturePreview(style, f)
|
||||
html += `<div class="ligature"><img src="${filename}"/><div>${ligature}</div></div>`
|
||||
})
|
||||
|
||||
html += `</div></body></html>`
|
||||
|
||||
fs.writeFileSync(`./images/preview/${style}/index.html`, html)
|
||||
}
|
||||
|
||||
const filenames = fs
|
||||
.readdirSync('./ligature/OperatorMonoSSmLig-Book/glyphs')
|
||||
.filter(f => !!f.match(/[^\d]\.liga\.xml$/))
|
||||
|
||||
generate('normal', filenames)
|
||||
generate('italic', filenames)
|
||||
@@ -0,0 +1,36 @@
|
||||
const fs = require('fs');
|
||||
const lig = `<Glyph name="LIG" lsb="0" width="625">
|
||||
<CharString>
|
||||
endchar
|
||||
</CharString>
|
||||
<Subrs/>
|
||||
<GlobalSubrs/>
|
||||
</Glyph>`;
|
||||
|
||||
fs.readdirSync('./ligature')
|
||||
.filter((f) => !!f.match(/^OperatorMono/))
|
||||
.forEach((f) => {
|
||||
console.log(f);
|
||||
fs.readdirSync(`./ligature/${f}/glyphs`)
|
||||
.filter((g) => !!g.match(/\.liga\.xml$/))
|
||||
.forEach((g) => {
|
||||
console.log(g);
|
||||
g.split('.')
|
||||
.slice(0, 1)
|
||||
.forEach((l) => {
|
||||
l.split('_').forEach((c) => {
|
||||
const path = `./ligature/${f}/glyphs/${c}.spacer.xml`;
|
||||
const exists = fs.existsSync(path);
|
||||
console.log(path, exists);
|
||||
if (exists) return;
|
||||
|
||||
const width = !!f.match(/SSm/) ? 625 : 600;
|
||||
const spacer = lig
|
||||
.replace('LIG', `${c}.spacer`)
|
||||
.replace('625', width);
|
||||
console.log(f, c, width);
|
||||
fs.writeFileSync(path, spacer);
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -1,288 +0,0 @@
|
||||
const xpath = require('xpath');
|
||||
const NodeType = {};
|
||||
NodeType.TEXT_NODE = 3;
|
||||
|
||||
let dom;
|
||||
let gsubDom;
|
||||
let scriptListDom;
|
||||
let featureListDom;
|
||||
let lookupListDom;
|
||||
let featureDom;
|
||||
let lookupIndex = 0;
|
||||
let chainIndex = 0;
|
||||
const substLookupMap = {};
|
||||
|
||||
const buildGsubTables = (_dom, ligature) => {
|
||||
dom = _dom;
|
||||
|
||||
if (/_/.test(ligature.glyph) === false) {
|
||||
// not a ligature, so see if glyph exists in font (as substitute)
|
||||
const glyphNode = xpath.select(
|
||||
`ttFont/GlyphOrder/GlyphID[@name="${ligature.name}"]`,
|
||||
dom,
|
||||
true
|
||||
);
|
||||
if (!glyphNode) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
const glyphs = ligature.name.replace(/\.liga$/, '').split('_');
|
||||
const isSingleGlyph = glyphs.length == 1;
|
||||
|
||||
gsubDom = xpath.select('ttFont/GSUB', dom, true);
|
||||
|
||||
// look for 'calt' feature
|
||||
featureListDom = xpath.select('FeatureList', gsubDom, true);
|
||||
|
||||
let featureRecord;
|
||||
const featureTag = xpath.select(
|
||||
'FeatureRecord/FeatureTag[@value="calt"]',
|
||||
featureListDom,
|
||||
true
|
||||
);
|
||||
if (!featureTag) {
|
||||
const featureListCount = xpath.select(
|
||||
'count(FeatureRecord)',
|
||||
featureListDom,
|
||||
true
|
||||
);
|
||||
featureRecord = createElementWithAttributes('FeatureRecord', {
|
||||
index: featureListCount
|
||||
});
|
||||
featureRecord.appendChild(
|
||||
createElementWithAttributes('FeatureTag', { value: 'calt' })
|
||||
);
|
||||
featureRecord.appendChild(dom.createElement('Feature'));
|
||||
featureListDom.appendChild(featureRecord);
|
||||
} else {
|
||||
featureRecord = featureTag.parentNode;
|
||||
}
|
||||
featureDom = xpath.select('Feature', featureRecord, true);
|
||||
|
||||
const featureIndex = featureRecord.getAttribute('index');
|
||||
|
||||
// add feature to scriptlist for DFLT and latn if not present
|
||||
addFeatureToScriptList('DFLT', featureIndex);
|
||||
addFeatureToScriptList('latn', featureIndex);
|
||||
|
||||
lookupListDom = xpath.select('LookupList', gsubDom, true);
|
||||
lookupIndex = xpath.select('count(Lookup)', lookupListDom, true);
|
||||
|
||||
const lookupDom = createElementWithAttributes('Lookup', {
|
||||
index: lookupIndex++
|
||||
});
|
||||
appendChildren(
|
||||
lookupDom,
|
||||
createElementWithAttributes('LookupType', { value: isSingleGlyph ? 1 : 6 }),
|
||||
createElementWithAttributes('LookupFlag', { value: 0 })
|
||||
);
|
||||
|
||||
// add contextual lookup to feature
|
||||
const featureLookupCount = xpath.select(
|
||||
'count(LookupListIndex)',
|
||||
featureDom,
|
||||
true
|
||||
);
|
||||
featureDom.appendChild(
|
||||
createElementWithAttributes('LookupListIndex', {
|
||||
index: featureLookupCount,
|
||||
value: lookupDom.getAttribute('index')
|
||||
})
|
||||
);
|
||||
|
||||
if (isSingleGlyph) {
|
||||
lookupDom.appendChild(
|
||||
getSubstLookup(ligature.name, ligature.glyph, lookupDom)
|
||||
);
|
||||
} else {
|
||||
lookupDom.appendChild(buildBacktrackFirst(glyphs));
|
||||
lookupDom.appendChild(buildLookAheadLast(glyphs));
|
||||
lookupDom.appendChild(buildLigatureSubst(glyphs, ligature.glyph));
|
||||
// remaining context
|
||||
for (let n = glyphs.length - 2; n >= 0; n--) {
|
||||
lookupDom.appendChild(
|
||||
buildChainContext(getLIGs(n), [glyphs[n]], glyphs.slice(n + 1), 'LIG')
|
||||
);
|
||||
}
|
||||
}
|
||||
lookupListDom.appendChild(lookupDom);
|
||||
};
|
||||
|
||||
const finalizeGsubTables = () => {
|
||||
// get current LookupList count
|
||||
let newIndex = xpath.select('count(Lookup)', lookupListDom, true);
|
||||
|
||||
// append added lookups
|
||||
Object.entries(substLookupMap).forEach(([, lookup]) => {
|
||||
// fixup existing lookups with new index
|
||||
const oldIndex = lookup.getAttribute('index');
|
||||
const substLookups = xpath.select(
|
||||
`//ChainContextSubst/SubstLookupRecord/LookupListIndex[@value="${oldIndex}"]`,
|
||||
lookupListDom,
|
||||
false
|
||||
);
|
||||
substLookups.forEach(substLookup => {
|
||||
substLookup.setAttribute('value', newIndex);
|
||||
});
|
||||
lookup.setAttribute('index', newIndex++);
|
||||
lookupListDom.appendChild(lookup);
|
||||
lookupListDom.appendChild(lookup);
|
||||
});
|
||||
};
|
||||
|
||||
//const dump = dom => console.log(format(serialize(dom)));
|
||||
|
||||
const addFeatureToScriptList = (tag, featureIndex) => {
|
||||
scriptListDom = xpath.select('ScriptList', gsubDom, true);
|
||||
const defaultLangSys = xpath.select(
|
||||
`ScriptRecord/ScriptTag[@value="${tag}"]/../Script/DefaultLangSys`,
|
||||
scriptListDom,
|
||||
true
|
||||
);
|
||||
const featureIndexNode = xpath.select(
|
||||
`FeatureIndex[@value=${featureIndex}]`,
|
||||
defaultLangSys,
|
||||
true
|
||||
);
|
||||
if (!featureIndexNode) {
|
||||
const count = xpath.select('count(FeatureIndex)', defaultLangSys, true);
|
||||
defaultLangSys.appendChild(
|
||||
createElementWithAttributes('FeatureIndex', {
|
||||
index: count,
|
||||
value: featureIndex
|
||||
})
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
const buildBacktrackFirst = glyphs => {
|
||||
// backtrack = first glyph
|
||||
// input = first glphy
|
||||
// lookAhead = [1..n]
|
||||
return buildChainContext([glyphs[0]], [glyphs[0]], glyphs.slice(1));
|
||||
};
|
||||
|
||||
const buildLookAheadLast = glyphs => {
|
||||
// backtrack = none
|
||||
// input = first glyph
|
||||
// lookAhead = [1..n] + [n]
|
||||
return buildChainContext(
|
||||
[],
|
||||
[glyphs[0]],
|
||||
[...glyphs.slice(1), glyphs.slice(-1)]
|
||||
);
|
||||
};
|
||||
|
||||
const buildLigatureSubst = (glyphs, lookup) => {
|
||||
// backtrack = LIG * n-1
|
||||
// input = last glyph
|
||||
// lookAhead = none
|
||||
return buildChainContext(
|
||||
getLIGs(glyphs.length - 1),
|
||||
glyphs.slice(-1),
|
||||
[],
|
||||
lookup
|
||||
);
|
||||
};
|
||||
|
||||
const getLIGs = length => new Array(length).fill('LIG', 0, length);
|
||||
|
||||
const buildChainContext = (backtrack, input, lookAhead, substitute) => {
|
||||
const chainDom = createElementWithAttributes('ChainContextSubst', {
|
||||
index: chainIndex++,
|
||||
Format: 3
|
||||
});
|
||||
|
||||
buildCoverage(chainDom, 'BacktrackCoverage', backtrack);
|
||||
buildCoverage(chainDom, 'InputCoverage', input);
|
||||
buildCoverage(chainDom, 'LookAheadCoverage', lookAhead);
|
||||
|
||||
if (substitute) {
|
||||
const lookup = getSubstLookup(input[0], substitute);
|
||||
const listIndex = lookup.getAttribute('index');
|
||||
const substLookupRecordDom = chainDom.appendChild(
|
||||
createElementWithAttributes('SubstLookupRecord', { index: 0 })
|
||||
);
|
||||
appendChildren(
|
||||
substLookupRecordDom,
|
||||
createElementWithAttributes('SequenceIndex', { value: 0 }),
|
||||
createElementWithAttributes('LookupListIndex', { value: listIndex })
|
||||
);
|
||||
}
|
||||
return chainDom;
|
||||
};
|
||||
|
||||
const buildCoverage = (chainDom, tagName, coverage) => {
|
||||
if (coverage) {
|
||||
coverage.forEach((glyph, i) => {
|
||||
const coverageDom = createElementWithAttributes(tagName, {
|
||||
index: i++,
|
||||
Format: 1
|
||||
});
|
||||
coverageDom.appendChild(
|
||||
createElementWithAttributes('Glyph', { value: glyph })
|
||||
);
|
||||
chainDom.appendChild(coverageDom);
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
const getSubstLookup = (input, output, lookupDom) => {
|
||||
if (!lookupDom) {
|
||||
lookupDom = substLookupMap[output];
|
||||
}
|
||||
|
||||
if (!lookupDom) {
|
||||
lookupDom = createElementWithAttributes('Lookup', {
|
||||
index: Object.keys(substLookupMap).length + 1
|
||||
});
|
||||
lookupDom.appendChild(
|
||||
createElementWithAttributes('LookupType', { value: 1 })
|
||||
);
|
||||
lookupDom.appendChild(
|
||||
createElementWithAttributes('LookupFlag', { value: 0 })
|
||||
);
|
||||
substLookupMap[output] = lookupDom;
|
||||
}
|
||||
|
||||
let singleSubstDom = xpath.select('SingleSubst', lookupDom, true);
|
||||
|
||||
if (!singleSubstDom) {
|
||||
singleSubstDom = createElementWithAttributes('SingleSubst', {
|
||||
index: 0,
|
||||
Format: 2
|
||||
});
|
||||
lookupDom.appendChild(singleSubstDom);
|
||||
}
|
||||
|
||||
// look for input subst
|
||||
const substitionDom = xpath.select(
|
||||
`Substitution[@in="${input}"]`,
|
||||
singleSubstDom,
|
||||
true
|
||||
);
|
||||
if (!substitionDom) {
|
||||
singleSubstDom.appendChild(
|
||||
createElementWithAttributes('Substitution', { in: input, out: output })
|
||||
);
|
||||
}
|
||||
return lookupDom;
|
||||
};
|
||||
|
||||
const createElementWithAttributes = (tagName, attributes) => {
|
||||
const element = dom.createElement(tagName);
|
||||
Object.entries(attributes).forEach(attribute => {
|
||||
element.setAttribute(attribute[0], attribute[1]);
|
||||
});
|
||||
return element;
|
||||
};
|
||||
|
||||
const appendChildren = (node, ...children) => {
|
||||
children.forEach(child => node.appendChild(child));
|
||||
};
|
||||
|
||||
//const serialize = dom => new XMLSerializer().serializeToString(dom);
|
||||
|
||||
exports.buildGsubTables = buildGsubTables;
|
||||
exports.finalizeGsubTables = finalizeGsubTables;
|
||||
|
After Width: | Height: | Size: 166 KiB |
|
After Width: | Height: | Size: 1.0 KiB |
|
After Width: | Height: | Size: 1.8 KiB |
|
After Width: | Height: | Size: 612 B |
|
After Width: | Height: | Size: 805 B |
|
After Width: | Height: | Size: 423 B |
|
After Width: | Height: | Size: 439 B |
|
After Width: | Height: | Size: 293 B |
|
After Width: | Height: | Size: 338 B |
|
After Width: | Height: | Size: 566 B |
|
After Width: | Height: | Size: 564 B |
|
After Width: | Height: | Size: 828 B |
|
After Width: | Height: | Size: 677 B |
|
After Width: | Height: | Size: 731 B |
|
After Width: | Height: | Size: 506 B |
|
After Width: | Height: | Size: 771 B |
|
After Width: | Height: | Size: 691 B |
|
After Width: | Height: | Size: 740 B |
|
After Width: | Height: | Size: 849 B |
|
After Width: | Height: | Size: 327 B |
|
After Width: | Height: | Size: 518 B |
|
After Width: | Height: | Size: 290 B |
|
After Width: | Height: | Size: 521 B |
@@ -0,0 +1,15 @@
|
||||
<html><head>
|
||||
<style>
|
||||
body { background-color: #000; color: #fff; font-family: sans-serif; margin: 16px;}
|
||||
a { color: #fff; text-decoration: none; padding: 4px;}
|
||||
a.active {color: #000; background-color: #fff;}
|
||||
.container { display: grid; grid-template-columns: repeat(auto-fill, minmax(200px, 1fr)); }
|
||||
.ligature { display: flex; flex-direction: column; align-items: center; margin: 8px; }
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<h1>Operator Mono Ligatures</h1>
|
||||
<a href="https://htmlpreview.github.io/?https://github.com/kiliman/operator-mono-lig/blob/master/images/preview/normal/index.html" class="">Normal</a> |
|
||||
<a href="https://htmlpreview.github.io/?https://github.com/kiliman/operator-mono-lig/blob/master/images/preview/italic/index.html" class="active">Italic</a>
|
||||
<div class="container">
|
||||
<div class="ligature"><img src="ampersand_ampersand.png"/><div>ampersand_ampersand</div></div><div class="ligature"><img src="asterisk_equal.png"/><div>asterisk_equal</div></div><div class="ligature"><img src="bar_bar.png"/><div>bar_bar</div></div><div class="ligature"><img src="bar_greater.png"/><div>bar_greater</div></div><div class="ligature"><img src="colon_colon.png"/><div>colon_colon</div></div><div class="ligature"><img src="colon_equal.png"/><div>colon_equal</div></div><div class="ligature"><img src="equal_equal.png"/><div>equal_equal</div></div><div class="ligature"><img src="equal_equal_equal.png"/><div>equal_equal_equal</div></div><div class="ligature"><img src="equal_equal_greater.png"/><div>equal_equal_greater</div></div><div class="ligature"><img src="equal_greater.png"/><div>equal_greater</div></div><div class="ligature"><img src="equal_less_less.png"/><div>equal_less_less</div></div><div class="ligature"><img src="exclam_equal.png"/><div>exclam_equal</div></div><div class="ligature"><img src="exclam_equal_equal.png"/><div>exclam_equal_equal</div></div><div class="ligature"><img src="exclam_exclam.png"/><div>exclam_exclam</div></div><div class="ligature"><img src="greater_equal.png"/><div>greater_equal</div></div><div class="ligature"><img src="greater_equal_greater.png"/><div>greater_equal_greater</div></div><div class="ligature"><img src="greater_greater.png"/><div>greater_greater</div></div><div class="ligature"><img src="greater_greater_equal.png"/><div>greater_greater_equal</div></div><div class="ligature"><img src="hyphen_equal.png"/><div>hyphen_equal</div></div><div class="ligature"><img src="hyphen_greater.png"/><div>hyphen_greater</div></div><div class="ligature"><img src="hyphen_hyphen.png"/><div>hyphen_hyphen</div></div><div class="ligature"><img src="hyphen_hyphen_greater.png"/><div>hyphen_hyphen_greater</div></div><div class="ligature"><img src="less_bar.png"/><div>less_bar</div></div><div class="ligature"><img src="less_equal.png"/><div>less_equal</div></div><div class="ligature"><img src="less_equal_equal.png"/><div>less_equal_equal</div></div><div class="ligature"><img src="less_equal_greater.png"/><div>less_equal_greater</div></div><div class="ligature"><img src="less_equal_less.png"/><div>less_equal_less</div></div><div class="ligature"><img src="less_exclam_hyphen_hyphen.png"/><div>less_exclam_hyphen_hyphen</div></div><div class="ligature"><img src="less_hyphen.png"/><div>less_hyphen</div></div><div class="ligature"><img src="less_hyphen_greater.png"/><div>less_hyphen_greater</div></div><div class="ligature"><img src="less_hyphen_hyphen.png"/><div>less_hyphen_hyphen</div></div><div class="ligature"><img src="less_less.png"/><div>less_less</div></div><div class="ligature"><img src="less_less_equal.png"/><div>less_less_equal</div></div><div class="ligature"><img src="less_slash.png"/><div>less_slash</div></div><div class="ligature"><img src="less_slash_greater.png"/><div>less_slash_greater</div></div><div class="ligature"><img src="plus_equal.png"/><div>plus_equal</div></div><div class="ligature"><img src="plus_plus.png"/><div>plus_plus</div></div><div class="ligature"><img src="question_question.png"/><div>question_question</div></div><div class="ligature"><img src="quotedbl_quotedbl_quotedbl.png"/><div>quotedbl_quotedbl_quotedbl</div></div><div class="ligature"><img src="quotesingle_quotesingle_quotesingle.png"/><div>quotesingle_quotesingle_quotesingle</div></div><div class="ligature"><img src="semicolon_semicolon.png"/><div>semicolon_semicolon</div></div><div class="ligature"><img src="slash_equal.png"/><div>slash_equal</div></div><div class="ligature"><img src="slash_greater.png"/><div>slash_greater</div></div><div class="ligature"><img src="underscore_underscore.png"/><div>underscore_underscore</div></div><div class="ligature"><img src="w_w_w.png"/><div>w_w_w</div></div></div></body></html>
|
||||
|
After Width: | Height: | Size: 799 B |
|
After Width: | Height: | Size: 775 B |
|
After Width: | Height: | Size: 571 B |
|
After Width: | Height: | Size: 798 B |
|
After Width: | Height: | Size: 692 B |
|
After Width: | Height: | Size: 737 B |
|
After Width: | Height: | Size: 529 B |
|
After Width: | Height: | Size: 754 B |
|
After Width: | Height: | Size: 527 B |
|
After Width: | Height: | Size: 714 B |
|
After Width: | Height: | Size: 861 B |
|
After Width: | Height: | Size: 795 B |
|
After Width: | Height: | Size: 998 B |
|
After Width: | Height: | Size: 484 B |
|
After Width: | Height: | Size: 497 B |
|
After Width: | Height: | Size: 760 B |
|
After Width: | Height: | Size: 1.8 KiB |
|
After Width: | Height: | Size: 1.8 KiB |
|
After Width: | Height: | Size: 1.8 KiB |
|
After Width: | Height: | Size: 633 B |
|
After Width: | Height: | Size: 791 B |
|
After Width: | Height: | Size: 245 B |
|
After Width: | Height: | Size: 678 B |
|
After Width: | Height: | Size: 1.1 KiB |
|
After Width: | Height: | Size: 1.2 KiB |
|
After Width: | Height: | Size: 283 B |
|
After Width: | Height: | Size: 646 B |
|
After Width: | Height: | Size: 408 B |
|
After Width: | Height: | Size: 374 B |
|
After Width: | Height: | Size: 281 B |
|
After Width: | Height: | Size: 320 B |
|
After Width: | Height: | Size: 571 B |