126 Commits

Author SHA1 Message Date
kiliman 3813319b42 🚀 Deploy v2.4.0 2020-12-13 10:16:02 -05:00
kiliman f2a61c74ad 🔀 Merge branch 'feature/use-fea-files' 2020-12-13 10:13:23 -05:00
kiliman 1fce61fe50 🔨 Update build to call fonttools feaLib 2020-12-13 10:11:28 -05:00
kiliman 1028c96291 🔥 Delete gsub.js and replace with calt feature 2020-12-13 10:07:52 -05:00
kiliman 043c160546 Add default feature file since feaLib replaces existing features 2020-12-13 10:06:11 -05:00
kiliman 445828c8bf Add function to generate calt feature file 2020-12-13 10:05:41 -05:00
kiliman 66fd3f94a1 🙈 Ignore all files in .vscode 2020-12-13 10:04:27 -05:00
kiliman 9bf5f6197c Add new spacer glyphs to replace LIG placeholder 2020-12-12 17:50:16 -05:00
Mark Skelton bd48389313 Update deps (#159)
* Fix eslint error

* Add repository to package.json

* Remove unused dependencies

* Update dev eslint deps
2020-12-09 14:21:23 -06:00
kiliman 30a6c098e7 🚀 Deploy v2.3.0 2020-05-13 08:41:16 -04:00
kiliman 42e64f84b8 🔀 Merge branch 'feature/italics-hack'
Fix #104
2020-05-13 08:40:43 -04:00
kiliman 124d893fe5 Add plus_equal.liga and update colon_equal.liga 2020-05-13 08:25:53 -04:00
kiliman e692fcfbf8 🔨 Make italics-hack the default option with ability to turn it off 2020-05-13 08:23:09 -04:00
kiliman 321486d19e 🐛 Add init function to only apply the hack once instead of per ligature 2020-05-12 12:05:21 -04:00
kiliman 6f3d00ae6d 🪓 Add hack for italics by removing existing GSUB tables 2020-05-12 09:36:58 -04:00
Mark Skelton 420eeefe59 Merge pull request #131 from kiliman/dependabot/npm_and_yarn/acorn-6.4.1
Bump acorn from 6.2.1 to 6.4.1
2020-04-14 13:30:53 -05:00
dependabot[bot] a5c360bf30 Bump acorn from 6.2.1 to 6.4.1
Bumps [acorn](https://github.com/acornjs/acorn) from 6.2.1 to 6.4.1.
- [Release notes](https://github.com/acornjs/acorn/releases)
- [Commits](https://github.com/acornjs/acorn/compare/6.2.1...6.4.1)

Signed-off-by: dependabot[bot] <support@github.com>
2020-04-04 21:23:15 +00:00
kiliman 93d4d03ef5 🚀 Deploy 2.2.8 with profiles fix 2020-03-09 17:13:26 -04:00
kiliman 59435e4ee8 😍 Add @Jakob6174 as a contributor 2020-03-09 17:12:36 -04:00
kiliman cad9759288 📝 Add comment for family name value 2020-03-09 17:10:52 -04:00
kiliman d3940070ed 🐛 Fix multiple font generation using profiles 2020-03-09 17:08:59 -04:00
Kiliman 320fb069f7 Merge pull request #130 from Jakob6174/master
Minor inconsistency in newly generated font names
2020-03-09 17:07:53 -04:00
Jakob6174 d6c1df83ed Minor inconsistency in newly generated fontnames, original font doesn't specify 'font weight' for this particular 'namerecord' 2020-03-09 16:23:33 +00:00
Amit Parekh 0b29866a3e Merge pull request #127 from leshow/master
output -> build
2020-01-10 02:26:43 +00:00
Evan Cameron 9a70d50924 Fix typo 2020-01-09 17:11:05 -05:00
kiliman 68741971f1 ⬆️ Update serialize-javascript to 2.1.2 2020-01-09 11:07:35 -05:00
Kiliman bfae141c75 Merge pull request #126 from kiliman/dependabot/npm_and_yarn/npm-6.13.4
⬆️ Bump npm from 5.7.1 to 6.13.4
2020-01-07 10:23:43 -05:00
Amit Parekh 844b55f7b2 GitBook: [master] 4 pages modified 2019-12-21 23:55:36 +00:00
Amit Parekh 0c226a60bc GitBook: [master] 5 pages modified 2019-12-21 23:54:58 +00:00
Amit Parekh 2dd2079309 GitBook: [master] 2 pages modified 2019-12-20 14:44:28 +00:00
Amit Parekh 6f14cd709a GitBook: [master] 4 pages and 11 assets modified 2019-12-20 14:40:43 +00:00
dependabot[bot] 06b5464fd6 Bump npm from 5.7.1 to 6.13.4
Bumps [npm](https://github.com/npm/cli) from 5.7.1 to 6.13.4.
- [Release notes](https://github.com/npm/cli/releases)
- [Changelog](https://github.com/npm/cli/blob/latest/CHANGELOG.md)
- [Commits](https://github.com/npm/cli/compare/v5.7.1...v6.13.4)

Signed-off-by: dependabot[bot] <support@github.com>
2019-12-13 19:32:26 +00:00
Mark Skelton dc2d35f1c5 Comment out single ligature request line 2019-11-09 11:48:50 -06:00
Mark Skelton 0823ed98af Create new ligature template 2019-11-09 11:46:35 -06:00
Amit Parekh 7b6eb72e66 GitBook: [master] 4 pages and 6 assets modified 2019-11-02 22:00:53 +00:00
Mark Skelton 53e9951957 Remove assets from docs 2019-11-01 18:05:20 -05:00
Mark Skelton 44fc9b5ead GitBook: [master] 2 pages and 6 assets modified 2019-11-01 23:04:39 +00:00
Mark Skelton a86034b38d Update gitbook config 2019-11-01 18:04:06 -05:00
Mark Skelton c1bb4a9197 Revert "GitBook: [master] 2 pages and 3 assets modified"
This reverts commit 77244583f0.
2019-11-01 18:02:42 -05:00
Mark Skelton 77244583f0 GitBook: [master] 2 pages and 3 assets modified 2019-11-01 23:01:38 +00:00
Kiliman f26cecc4bf Merge pull request #119 from kiliman/gitbook
Create gitbook.yml
2019-11-01 18:56:21 -04:00
Mark Skelton 732a29a79f Create gitbook.yml 2019-11-01 17:43:20 -05:00
kiliman 258531d577 😍 Add @CandySunPlus as a contributor 2019-10-31 14:15:45 -04:00
kiliman 4cf344a435 🚀 Deploy v2.2.7 with less_hyphen_greater ligature 2019-10-31 14:13:31 -04:00
kiliman 63002e7901 Add less_hyphen_greater ligature for all weights by @CandySunPlus 2019-10-31 14:12:45 -04:00
kiliman 38eb637717 🚀 Deploy to v2.2.6 with www ligature for SSm Book/Italic 2019-10-31 13:42:59 -04:00
Kiliman 2dbdb2543c Merge pull request #118 from kiliman/feature/ligature_www
🔀 Add www ligature from @amitkparekh
2019-10-31 13:34:32 -04:00
Amit Parekh 4b908ad07b Add @amitkparekh as a contributor 2019-10-31 17:20:49 +00:00
Amit Parekh a6dc28a403 Add glyph: w_w_w [SSm Book Italic] 2019-10-31 17:20:26 +00:00
Amit Parekh 84a4863e1f Add glyph: w_w_w [SSm Book] 2019-10-31 17:20:14 +00:00
Mark Skelton 6fe2acd518 Update readme 2019-10-31 09:53:34 -04:00
Mark Skelton 25051cfb52 Merge pull request #114 from kiliman/mskelton-rename
Mskelton rename
2019-10-18 21:53:25 -05:00
Mark Skelton f91b91b7df Update README.md 2019-10-18 21:53:01 -05:00
Mark Skelton 1ed5f8afe4 Update README.md 2019-10-18 21:51:48 -05:00
Mark Skelton e87797d070 Update .all-contributorsrc 2019-10-18 21:51:15 -05:00
kiliman 4e50610989 🚀 Deploy v2.2.5 with Operator Mono Book/Italic ligatures 2019-09-30 20:09:35 -04:00
kiliman 009dac1619 Add Operator Mono Book Light ligatures 2019-09-30 20:07:11 -04:00
kiliman 43d7f44527 Add Operator Mono Book ligatures 2019-09-30 20:07:11 -04:00
kiliman 9abc800918 ⬆️ Update package-lock.json version 2019-09-19 10:55:12 -04:00
kiliman 10027973d8 😍 Add @drod3763 as a contributor 2019-09-19 10:52:57 -04:00
Derick Rodriguez a9b6b1305d Update README.md to document Docker install method 2019-09-19 10:47:33 -04:00
Kiliman 85cdb5c0a4 📝 Update to v2.2.4 add missing ligatures 2019-08-07 09:08:04 -04:00
Kiliman 22d1a4d16d 🔀 Merge branch 'add-missing-ligatures' into develop 2019-08-07 09:00:12 -04:00
Mark Skelton 59466b8dfa Add missing light and light italic ligatures 2019-08-07 06:23:13 -05:00
Kiliman 2ed7ab50b3 📝 Update to v2.2.3 Operator Mono SSm Book Italic ligatures 2019-08-06 09:06:23 -04:00
Kiliman 37caa3ddea 🔀 Merge branch 'book-italic' into develop 2019-08-06 09:05:20 -04:00
Mark Skelton b70accff53 Update book italic ligatures 2019-08-05 22:07:54 -05:00
Kiliman da7425fbe9 📝 Update to v2.2.2 fixes some ligatures not in correct weight 2019-08-05 12:07:18 -04:00
Kiliman 2282dd3d5d 📝 Update to v2.2.1 with fix for Operator Mono Light (non-SSm) widths 2019-08-04 21:15:16 -04:00
Kiliman d7e18a4962 🐛 Fix Light/Light Italic to use width 550 vs 625 of ScreenSmart
Fixes #97
2019-08-04 21:12:31 -04:00
Kiliman d71b04356a 📝 Update README for v2.2 includes new SSm Light, Medium, and Bold 2019-08-04 18:29:14 -04:00
Kiliman 651edc2b62 Add complete set of SSm Light/Italic ligatures 2019-08-04 18:20:38 -04:00
Kiliman 02818d15a9 Add complete set of SSm Medium/Italic ligatures 2019-08-04 18:06:55 -04:00
Kiliman 5c9a5d51a8 🔨 Complete SSm Bold/Italic ligatures 2019-08-04 17:42:25 -04:00
Kiliman fc180099b8 📝 Update README for v2.1 includes new OM Light and contributor shoutout 2019-08-02 12:16:50 -04:00
Kiliman 1f5712ecae 😍 Add contributors @kiliman and @markypython 2019-08-02 12:15:40 -04:00
Kiliman 2cbf9d84cb 🔧 Add all-contributors package 2019-08-02 12:14:54 -04:00
Kiliman d1c8620f6d 🔨 Update Operator Mono Light and Light Italic ligatures 2019-08-02 11:40:51 -04:00
Kiliman 0f10f62920 🔀 Merge branch 'bold-italic-ligatures' into develop 2019-08-02 11:22:51 -04:00
Mark Skelton fd4b980b7c Update bold ligatures 2019-07-31 19:48:59 -05:00
Mark Skelton 286e5f0820 Add colon equal for bold 2019-07-31 19:48:51 -05:00
Mark Skelton 6e66c37704 Update bold ligatures 2019-07-31 19:33:01 -05:00
Mark Skelton ad3050a731 Add ampersand ampersand and colon equal 2019-07-31 19:32:41 -05:00
Mark Skelton da1abf02c6 Add more bold italic ligatures 2019-07-31 19:30:09 -05:00
Kiliman 3a03d21c90 🔀 Merge branch 'bold-italic-ligatures' into develop 2019-07-31 08:47:07 -04:00
Mark Skelton 05bc5eaa4e Update bold glyphs 2019-07-30 19:02:13 -05:00
Mark Skelton 03114bf88d Add bold italic powerline and LIG glyphs 2019-07-30 19:02:07 -05:00
Mark Skelton 83f9a6d170 Add powerline ligatures 2019-07-30 19:00:07 -05:00
Kiliman f0a883ee62 ⬆️ Upgrade package dependencies (npm audit) 2019-07-30 12:41:26 -04:00
Kiliman 6e3415763c 🔀 Merge branch 'bold-ligatures' into develop 2019-07-30 12:30:12 -04:00
Mark Skelton 2bdf134f70 Update ligatures 2019-07-30 07:24:17 -05:00
Mark Skelton edbbc78b82 Update config files 2019-07-30 07:23:03 -05:00
Mark Skelton 4edf9bc945 Add more ligatures 2019-07-30 07:22:01 -05:00
Mark Skelton 538de4ad67 Add lig and equal greater ligatures 2019-07-28 16:01:57 -05:00
Mark Skelton 3550ee0bb1 Add config files 2019-07-28 16:01:48 -05:00
Mark Skelton 65b938fdc1 Add names.json for bold font 2019-07-28 15:59:49 -05:00
Kiliman c5112089cb 🔀 Merge branch 'develop' 2019-07-26 16:37:28 -04:00
Kiliman 22ebd8aab7 📝 Update README for v2.0 2019-07-26 16:33:47 -04:00
Kiliman fe530d1ea9 Update glyphs 2019-07-26 16:33:17 -04:00
Kiliman 19727aecc5 Merge branch 'features/contextsubst' into develop 2019-07-24 09:58:47 -04:00
Kiliman 7a3be9b579 💄 Update Go sample file 2019-07-24 09:58:01 -04:00
Kiliman 371be6a082 🎨 Prettier formatting 2019-07-24 09:58:01 -04:00
Kiliman 86b1d66f15 🚨 Remove linter warning unused variable 2019-07-24 09:58:01 -04:00
Kiliman 5538ffe2b5 💄 Update sample HTML file 2019-07-24 09:58:01 -04:00
Kiliman 360402a197 ️ Add support for mapping non-ligature glyphs 2019-07-24 09:58:01 -04:00
Kiliman f7cafe55b3 Add Go sample 2019-07-24 09:58:01 -04:00
Kiliman 9cef42b1fb 🐛 Fix errors if glyphs don't exist for other font weights 2019-07-24 09:58:01 -04:00
Kiliman 8360f4ad81 🐛 Fix profile parsing 2019-07-24 09:58:01 -04:00
Kiliman 73f188856f Add glyphs for SSm Book Italic 2019-07-24 09:58:01 -04:00
Kiliman d2c63ad1ca Add glyph: underscore_underscore 2019-07-24 09:58:01 -04:00
Kiliman 0a7eca61d4 Add glyphs: colon_equal, greater_equal.2, less_equal.2, percent.alt 2019-07-24 09:58:01 -04:00
Kiliman fc8827e17c Remove elements from head that change but we don't care about 2019-07-24 09:58:01 -04:00
Kiliman 150ed13829 Add file (list of patterns) for matching exported glyphs 2019-07-24 09:58:01 -04:00
Kiliman 502f445758 Add Powerline glyps 2019-07-24 09:58:01 -04:00
Kiliman d3c5604090 Add </ and /> ligatures 2019-07-24 09:58:01 -04:00
Kiliman 61cfbf075d Regenerate ligature glyphs 2019-07-24 09:58:01 -04:00
Kiliman 28eb8b58e5 Add support for non-ligature glyphs 2019-07-24 09:58:01 -04:00
Emanuele Ballarin 91c4421765 Make drop-in compatible with previous implementation
Fixed variable types, now everything gathered from original fonts or property JSONs, and everything passed as font properties is 'const'.
2019-07-24 09:57:20 -04:00
Emanuele Ballarin 3ed59809de Revert useless whitespace-only modifications
Fix for an autoformatter side-effect.
2019-07-24 09:57:20 -04:00
Emanuele Ballarin 660c719779 Fix font family names in PS and TTF metadata
Fix font family names in PS and TTF metadata, as already defined in original font and master branch
2019-07-24 09:57:20 -04:00
kiliman 610140f1de Start work in progress for Operator Mono Light 2019-07-24 09:57:20 -04:00
kiliman b6f785bfc7 Add new generated glyphs for SSm Book and Book Italic 2019-07-24 09:57:20 -04:00
kiliman bc46df5f1c Update sample.js with new ligatures 2019-07-24 09:57:20 -04:00
kiliman 5f13b9c918 Update packages and add eslint config 2019-07-24 09:57:20 -04:00
kiliman 9398884dc6 Update extract and build process with support for context substitutions 2019-07-24 09:57:20 -04:00
kiliman 036e837e0c Remove old generated files 2019-07-24 09:57:20 -04:00
777 changed files with 23927 additions and 27355 deletions
+72
View File
@@ -0,0 +1,72 @@
{
"projectName": "operator-mono-lig",
"projectOwner": "kiliman",
"repoType": "github",
"repoHost": "https://github.com",
"files": [
"README.md"
],
"imageSize": 100,
"commit": true,
"commitConvention": "none",
"contributors": [
{
"login": "kiliman",
"name": "Kiliman",
"avatar_url": "https://avatars3.githubusercontent.com/u/47168?v=4",
"profile": "https://github.com/kiliman",
"contributions": [
"code",
"doc",
"design"
]
},
{
"login": "mskelton",
"name": "Mark Skelton",
"avatar_url": "https://avatars3.githubusercontent.com/u/25914066?v=4",
"profile": "https://github.com/mskelton",
"contributions": [
"design"
]
},
{
"login": "drod3763",
"name": "Derick Rodriguez",
"avatar_url": "https://avatars2.githubusercontent.com/u/7785716?v=4",
"profile": "https://github.com/drod3763",
"contributions": [
"doc"
]
},
{
"login": "amitkparekh",
"name": "Amit Parekh",
"avatar_url": "https://avatars3.githubusercontent.com/u/7276308?v=4",
"profile": "https://github.com/amitkparekh",
"contributions": [
"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"
]
}
],
"contributorsPerLine": 7
}
+17
View File
@@ -0,0 +1,17 @@
module.exports = {
env: {
es6: true,
node: true
},
extends: 'eslint:recommended',
parserOptions: {
sourceType: 'module'
},
rules: {
indent: ['error', 2],
'linebreak-style': ['error', 'unix'],
quotes: ['error', 'single'],
semi: ['error', 'always'],
'no-console': 'off'
}
};
+1
View File
@@ -0,0 +1 @@
root: ./docs
+47
View File
@@ -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
+2 -1
View File
@@ -1,4 +1,5 @@
build
node_modules
.vscode/launch.json
.idea
.vscode
.DS_Store
+127 -76
View File
@@ -1,12 +1,42 @@
# Operator Mono Ligatures
[![All Contributors](https://img.shields.io/badge/all_contributors-6-orange.svg?style=flat-square)](#contributors-)
<img src="./images/operator-mono-lig.png" />
This project will generate new OpenType fonts for [Operator Mono](https://www.typography.com/fonts/operator/styles/) that includes ligatures similar to
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.
These ligatures were custom created using [Glyphs](https://glyphsapp.com/).
There are even italic versions of the ligatures.
## Take the poll
## 🎉 What's New in Version 2
<img src="./images/new-ligatures.png"/>
All new redesigned ligatures with better hinting. Updated font generation to support advanced OpenType features
like those found in Fira Code. For example, the cursor now moves inside the ligature. It also handles repeating
characters properly.
<img src="./images/caret-position.gif" />
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.
- Operator Mono SSm Light/Light Italic
- Operator Mono SSm Book/Book Italic
- Operator Mono SSm Medium/Medium Italic
- Operator Mono SSm Bold/Bold Italic
- Operator Mono Light/Light Italic
- Operator Mono Book/Book Italic
## 🙏 Help Wanted
As noted above, v2 does not include all weights for Operator Mono. In order to update the other fonts, all the ligatures need to be redone. Unfortunately I just don't have the time to do that at the moment. If you have a Mac and are interested in helping, please let me know. I will even purchase a license to Gylphs Mini for you.
You can reach me at kiliman@gmail.com.
## ☑️ Take the poll
Which font weight of Operator Mono do you use? Also note difference between Screen Smart (SSm) and regular version. This will help prioritize the order of development.
@@ -17,101 +47,122 @@ Which font weight of Operator Mono do you use? Also note difference between Scre
[![](https://api.gh-polls.com/poll/01C6T4C3FBG21KVS7FAW7Z09B2/Operator%20Mono%20Medium)](https://api.gh-polls.com/poll/01C6T4C3FBG21KVS7FAW7Z09B2/Operator%20Mono%20Medium/vote)
[![](https://api.gh-polls.com/poll/01C6T4C3FBG21KVS7FAW7Z09B2/Operator%20Mono%20Light)](https://api.gh-polls.com/poll/01C6T4C3FBG21KVS7FAW7Z09B2/Operator%20Mono%20Light/vote)
I have updated the following fonts:
## ScreenSmart versions
* Operator Mono SSm Book
* Operator Mono SSm Book Italic
* Operator Mono SSm Medium
* Operator Mono SSm Medium Italic
* Operator Mono SSm Light
* Operator Mono SSm Light Italic (**coming soon**)
## Regular versions
* Operator Mono Book
* Operator Mono Book Italic
* Operator Mono Medium
* Operator Mono Medium Italic
**Operator Mono SSm Book**
<img src="./images/operator-mono-ssm-book.png" />
**Operator Mono SSm Medium**
<img src="./images/operator-mono-ssm-medium.png" />
**Creating ligatures using Glyphs**
<img src="./images/glyphs-screenshot.png" />
**YouTube video (click to view)**
[![Using Glyphs app to create ligatures for Operator Mono font](https://img.youtube.com/vi/ttI3W5Dh54E/0.jpg)](https://youtu.be/ttI3W5Dh54E)
>NOTE: Because *Operator Mono* is not a free font, you must have the original font files. This utility
will merge the ligature definitions into a copy of the original font. The new font family is named *Operator Mono Lig* so you can install it side-by-side with the original font.
> NOTE: Because _Operator Mono_ is not a free font, you must have the original font files. This utility
> will merge the ligature definitions into a copy of the original font. The new font family is named _Operator Mono Lig_ so you can install it side-by-side with the original font.
## Prerequisites
* The original *Operator Mono* font... of course.
* Install *fonttools* from https://github.com/fonttools/fonttools
* Install Python
* Run: `pip install fonttools` (for Mac users it's better run `pip3 install fonttools` - [info](https://stackoverflow.com/a/33416270/3191011))
* Node.js (**version 7.6+ for async/await support**)
## How to Install
- The original _Operator Mono_ font... of course.
- Python (v2.7+)
- Node.js
- Install _fonttools_ from https://github.com/fonttools/fonttools
- Windows/Linux: `pip install fonttools`
- Mac: `pip3 install fonttools`
1. Once all the prerequisites have been installed, clone this repo.
## Installation
2. From the command line, run:
Once all the prerequisites have been installed, clone this repo or download latest release from [Releases](https://github.com/kiliman/operator-mono-lig/releases) and unzip.
```
Next, copy your _Operator Mono_ OpenType files into the `original` folder. **NOTE**: Filenames must not include spaces. It should look like:
- OperatorMonoSSm-Book.otf
- OperatorMonoSSm-BookItalic.otf
- OperatorMono-Light.otf
- OperatorMono-LightItalic.otf
- etc.
Finally, run the following commands to install npm dependencies and build the font files. The new font files will be placed in the `build` folder. You can now install these fonts on your system.
```sh
npm install
```
3. Copy your *Operator Mono* OpenType files into the `original` folder.
- **NOTE**: File names must strictly be of the form `OperatorMono-[Book/BookItalic/Medium/MediumItalic].otf`.
4. From the command line, run:
### Windows
```
# Windows
build
```
### Linux/Mac
```
# Linux/Mac
./build.sh
```
This will generate the new font files in the `build` folder. You can now install these fonts on your system.
### Docker
---
If you use Docker, you can also use the executable Docker image [here](https://github.com/drod3763/kiliman-operator-mono-lig-docker). It handles all the prerequisite installation for you, you just need to:
<img src="./images/OperatorMonoAllTheThings.png" />
1. Clone the repo [located here](https://github.com/drod3763/kiliman-operator-mono-lig-docker).
1. Copy your _Operator Mono_ OpenType files into the `input` folder.
1. From the command line run:
```sh
docker-compose run --rm operator-mono-lig
```
## GitHub
Add *Operator Mono* to GitHub code blocks using the [Stylus Extension](https://chrome.google.com/webstore/detail/stylus/clngdbkpkpeebahjckkjfobafhncgmne).
The image will build and execute the conversion. The new font files will be generated into the `build` folder.
Create a style and enter the following:
## Configure Your Code Editor
```css
.blob-code-inner, .blob-num, .highlight pre { font-family: "Operator Mono Lig" !important; font-size: 16px !important; }
.pl-c, .pl-e { font-style: italic; }
.pl-c { color: #4CAF50; }
You can now select the newly generated font in your code editor. Make sure you enable font ligatures and set the desired font weight if using Windows. The code block below shows what this might look like if using VS Code.
```json
"editor.fontFamily": "OperatorMonoSSmLig-Book",
"editor.fontLigatures": true,
// for Windows
"editor.fontFamily": "Operator Mono SSm Lig",
"editor.fontLigatures": true,
"editor.fontWeight": "500", // adjust for desired weight
```
<img src="./images/github-operatormono.png" />
## Visual Studio
## 🔧 Customize the generated font
You can have Visual Studio display the nice *Operator Mono* italic font for comments, using the [CommentsPlus Extension](https://marketplace.visualstudio.com/items?itemName=mhoumann.CommentsPlus).
By default, all available ligatures will be added to the generated font. However, if you don't like a particular
ligature, or would prefer to use an alternate glyph, you can create a `profiles.ini` file in the `./original` folder
to configure how the font should be built.
<img src="./images/vsoperatormono.png" />
You can create one or more profiles. Each profile will have a set of directives. You can specify alternate glyphs for
a given ligature. You can also prevent a ligature from being added.
## Hyper shell
Each profile will be listed with `[profile name]` (the first profile should be named default). The generated font will
include the profile name. For example `[Go]` would generate the font: _Operator Mono Lig Go_. This way you can configure
a different set of ligatures for each language in your favorite code editor.
Add *Operator Mono* to [Hyper](https://hyper.is/) a JS/CSS/HTML Terminal.
```ini
# name of profile (one or more sections, first should be name default)
[default]
# glyph=altglyph
greater_equal.liga=greater_equal.2.liga
<img src="./images/hyper terminal.png" />
# do not include glyph (add ! prefix)
!equal_equal.liga
# another optional section (will create a font named Operator Mono Lig Go)
[Go]
... add custom directives for this font ...
```
## 😍 Thank You
Thanks to Hoefler&Co for making such an amazing font. It makes writing code truly pleasurable.
Thanks also to all of you for your kinds words of encouragement and feedback. I really
appreciate it.
## ✨ Contributors
Thanks goes to these wonderful people ([emoji key](https://allcontributors.org/docs/en/emoji-key)):
<!-- ALL-CONTRIBUTORS-LIST:START - Do not remove or modify this section -->
<!-- prettier-ignore-start -->
<!-- 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/CandySunPlus"><img src="https://avatars0.githubusercontent.com/u/502700?v=4" width="100px;" alt="NikSun"/><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" width="100px;" alt="Jakob Pearson"/><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>
</tr>
</table>
<!-- markdownlint-enable -->
<!-- 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!
+13 -5
View File
@@ -3,26 +3,34 @@ 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
if not exist .\ligature\%lig%\charstrings.xml exit /b
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
fonttools feaLib -v -o ".\build\%lig%.otf" .\features\default.fea ".\build\%lig%.otf"
exit /b
+16 -6
View File
@@ -4,30 +4,40 @@ mkdir -p build
build_font() {
lig="$1"
flags="$2"
otf=${lig/Lig-/-}
if [ ! -e "./original/$otf.otf" ]
then
return
fi
if [ ! -e "./ligature/$lig/charstrings.xml" ]
if [ ! -e "./ligature/$lig/glyphs" ]
then
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"
fonttools feaLib -v -o "./build/$1.otf" ./features/default.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
+66
View File
@@ -0,0 +1,66 @@
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 = {};
console.log(ligatures);
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;
Binary file not shown.

After

Width:  |  Height:  |  Size: 81 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 81 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 22 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 273 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 321 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 27 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 329 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 378 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 157 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 203 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 86 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 22 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 218 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 175 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 175 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 33 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 33 KiB

+4
View File
@@ -0,0 +1,4 @@
# Introduction
Testing
+19
View File
@@ -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)
+26
View File
@@ -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):
![](../.gitbook/assets/image%20%288%29.png)
@@ -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'
```
+6
View File
@@ -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.
![Settings for the middle guide for the Roman ligature](../../.gitbook/assets/image%20%281%29.png)
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\):
![Settings for the dimensions of the inner-brace](../../.gitbook/assets/image%20%283%29.png)
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:
![](../../.gitbook/assets/image%20%287%29.png)
Create a new guide and move the guide so it intersects the pointy inner-corner of the larger brace
![](../../.gitbook/assets/image%20%286%29.png)
Move the smaller brace vertically \(up/down\) so the two pointy inner-corner bits cross like so:
![](../../.gitbook/assets/image.png)
## Creating the italic ligature
Repeat all the steps as above ligature above **BUT set the middle guide** **to**:
![Middle-guide settings for the italic ligature](../../.gitbook/assets/image%20%289%29.png)
## Final ligatures
![\`{{\` roman ligature](../../.gitbook/assets/image%20%284%29.png)
![\`}}\` roman ligature](../../.gitbook/assets/image%20%282%29.png)
![\`{{\` italic ligature](../../.gitbook/assets/image%20%2810%29.png)
![\`}}\` italic ligature](../../.gitbook/assets/image%20%285%29.png)
@@ -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 -&gt; Add Guide\)
3. Set the settings on the guide as so:
+2
View File
@@ -0,0 +1,2 @@
# www
+174 -58
View File
@@ -1,38 +1,64 @@
const Promise = require('bluebird');
const fs = Promise.promisifyAll(require('fs'));
const fs = require('fs');
const os = require('os');
if (!os.EOL) {
os.EOL = process.platform === 'win32' ? '\r\n' : '\n';
}
const xpath = require('xpath');
const { DOMParser, XMLSerializer } = require('xmldom');
const format = require('xml-formatter');
const hash = require('hash.js');
let fontName;
const regEx = /\.liga$/;
const regExBlankLines = /^(?=\n)$|^\s*/gm;
const regExWhitespace = /^\s+$/;
const NodeType = {};
NodeType.TEXT_NODE = 3;
async function main() {
function main() {
fontName = process.argv[2];
const glyphsRegEx = getGlyphsRegEx('./ligature_source/glyphs');
const srcFileName = `./ligature_source/${fontName}.ttx`;
const folder = `./ligature/${fontName}`;
const fileName = `./${folder}/names.json`;
if (!fs.existsSync(fileName)) {
return 0;
}
console.log(`Reading file ${srcFileName}`);
const xml = await fs.readFileAsync(srcFileName, 'utf-8');
const xml = fs.readFileSync(srcFileName, 'utf-8');
const dom = new DOMParser().parseFromString(xml);
await extractAndWrite('charstrings', extractCharStrings, dom);
await extractAndWrite('config', extractConfig, dom);
await extractAndWrite('gpos', extractGpos, dom);
await extractAndWrite('gsub', extractGsub, dom);
await extractAndWrite('hmtx', extractHmtx, dom);
await extractAndWrite('subrs', extractSubrs, dom);
await extractAndWrite('gsubrs', extractGlobalSubrs, dom);
extractAndWrite('config', extractConfig, dom);
extractCharStrings(dom, glyphsRegEx);
extractAndWrite('subrs', extractSubrs, dom);
extractAndWrite('gsubrs', extractGlobalSubrs, dom);
console.log('Done');
}
async function extractAndWrite(name, func, dom) {
function getGlyphsRegEx(path) {
const glyphs = fs.readFileSync(path, 'utf-8');
const patterns = ['LIG'];
glyphs
.split(os.EOL)
.filter(line => line.length > 0)
.forEach(line => {
const pattern = line
.replace(/\s*#.*/, '')
.replace(/[.]/g, '\\.')
.replace(/[*]/g, '.*');
if (pattern.length) {
patterns.push(pattern);
}
});
return new RegExp(`^(${patterns.join('|')})$`);
}
function extractAndWrite(name, func, dom) {
const newDom = func(dom);
console.log('Finished extracting ' + name);
@@ -41,30 +67,23 @@ async function extractAndWrite(name, func, dom) {
if (!fs.existsSync(folder)) {
fs.mkdirSync(folder);
}
await fs.writeFileAsync(fileName, format(serialize(newDom)));
fs.writeFileSync(fileName, format(serialize(newDom)));
console.log('Finished writing ' + name);
}
const serialize = dom =>
new XMLSerializer().serializeToString(dom, false, node => {
if (node.nodeType === NodeType.TEXT_NODE) {
if (regExWhitespace.test(node.data)) return null;
const data = node.data
.split('\r\n')
.filter(s => /\S+/.test(s))
.map(s => s.replace(/^\s+/g, ''))
.join('\n');
return node.ownerDocument.createTextNode(data);
}
return node;
});
//const dump = dom => console.log(serialize(dom));
const serialize = dom => new XMLSerializer().serializeToString(dom);
const extractConfig = dom => {
const newDom = new DOMParser().parseFromString('<ttFont/>');
const head = xpath.select('/ttFont/head', dom, true);
const hhea = xpath.select('/ttFont/hhea', dom, true);
// remove elements that change after each save
// but we don't care about
head.removeChild(xpath.select('checkSumAdjustment', head, true));
head.removeChild(xpath.select('created', head, true));
head.removeChild(xpath.select('modified', head, true));
const bbox = extractFromPath('/ttFont/CFF/CFFFont/FontBBox', dom);
const widthX = extractFromPath(
'/ttFont/CFF/CFFFont/Private/nominalWidthX',
@@ -92,39 +111,136 @@ const extractFromPath = (path, dom) => {
return newDom.documentElement;
};
const extractGpos = dom => {
const gpos = xpath.select('/ttFont/GPOS', dom, true);
return gpos;
};
const extractGsub = dom => {
const gsub = xpath.select('/ttFont/GSUB', dom, true);
return gsub;
};
const extractHmtx = dom => {
const newDom = new DOMParser().parseFromString('<hmtx/>');
const mtx = xpath.select('/ttFont/hmtx/mtx', dom);
mtx
.filter(node => regEx.test(node.getAttribute('name')))
.forEach(node => newDom.documentElement.appendChild(node));
return newDom;
};
const extractCharStrings = dom => {
const newDom = new DOMParser().parseFromString('<CharStrings/>');
const extractCharStrings = (dom, glyphsRegEx) => {
const charStrings = xpath.select(
'/ttFont/CFF/CFFFont/CharStrings/CharString',
dom
);
charStrings
.filter(node => regEx.test(node.getAttribute('name')))
.forEach(node => newDom.documentElement.appendChild(node));
.filter(node => glyphsRegEx.test(node.getAttribute('name')))
.forEach(node => writeGlyphData(dom, node));
console.log('Finished writing charstrings');
};
return newDom;
const writeGlyphData = (dom, node) => {
const newDom = new DOMParser().parseFromString('<Glyph/>').documentElement;
const name = node.getAttribute('name');
newDom.setAttribute('name', name);
// get map and set code
const map = xpath.select(
`/ttFont/cmap/cmap_format_4/map[@name="${name}"]`,
dom,
true
);
if (map) {
newDom.setAttribute('code', map.getAttribute('code'));
}
// get mtx
const mtx = xpath.select(`/ttFont/hmtx/mtx[@name="${name}"]`, dom, true);
newDom.setAttribute('lsb', mtx.getAttribute('lsb'));
newDom.setAttribute('width', mtx.getAttribute('width'));
const charStringDom = dom.createElement('CharString');
const subrsDom = dom.createElement('Subrs');
const gsubrsDom = dom.createElement('GlobalSubrs');
newDom.appendChild(charStringDom);
newDom.appendChild(subrsDom);
newDom.appendChild(gsubrsDom);
const subrs = {
map: [],
fingerprints: [],
sourcePath: '/ttFont/CFF/CFFFont/Private/Subrs',
target: subrsDom
};
const gsubrs = {
map: [],
fingerprints: [],
sourcePath: '/ttFont/CFF/GlobalSubrs',
target: gsubrsDom
};
extractCharStringSubrs(dom, node, subrs, gsubrs, 8);
const outline = indentTextContent(node.childNodes[0].textContent, 8);
charStringDom.appendChild(dom.createTextNode(outline));
const folder = `./ligature/${fontName}/glyphs`;
const fileName = `./${folder}/${name}.xml`;
if (!fs.existsSync(folder)) {
fs.mkdirSync(folder);
}
fs.writeFileSync(fileName, format(serialize(newDom)));
console.log('* ' + name);
};
const extractCharStringSubrs = (dom, node, subrs, gsubrs, indent) => {
// check for callsubr/callgsubr
const lines = node.childNodes[0].textContent.split(os.EOL);
const newLines = [];
let fingerprint = '';
lines.forEach(line => {
if (line.trim().length === 0) return;
const matches = line.match(/(.*?)(-?\d+) (callsubr|callgsubr)$/);
if (matches != null) {
const { map, fingerprints, sourcePath, target } =
matches[3] === 'callsubr' ? subrs : gsubrs;
const index = matches[2];
const srcIndex = parseInt(index) + 107;
let newIndex = map[srcIndex];
if (!newIndex) {
// find subr in source dom and copy to target dom
const srcSubr = xpath.select(
`/${sourcePath}/CharString[@index="${srcIndex}"]`,
dom,
true
);
// append subr to target dom and get new index
newIndex = xpath.select('count(CharString)', target, true);
map[srcIndex] = newIndex;
const clone = srcSubr.cloneNode(true);
clone.setAttribute('index', newIndex);
target.appendChild(clone);
// patch up source in case it also has any callsubrs
fingerprint = extractCharStringSubrs(dom, clone, subrs, gsubrs, 12);
fingerprints[newIndex] = fingerprint;
} else {
fingerprint = fingerprints[newIndex];
}
// rewrite line with fingerprint
line = `${matches[1]}{${fingerprint}} ${matches[3]}`;
}
newLines.push(line.trim());
});
const content = newLines.join('\n');
fingerprint = hash
.sha256()
.update(content)
.digest('hex')
.substr(0, 8);
node.setAttribute('fingerprint', fingerprint);
node.childNodes[0].textContent = indentTextContent(content, indent);
return fingerprint;
};
const indentTextContent = (text, indent) => {
return text
.split('\n')
.map(line => ' '.repeat(indent) + line.trim())
.join('\n')
.trim();
};
const extractSubrs = dom => {
+1 -1
View File
@@ -15,6 +15,6 @@ then
else
# build all available fonts
for f in ./ligature_source/*.otf ; do
extract_font $(basename $f)
extract_font `basename "${f%.*}"`
done
fi
+1
View File
@@ -0,0 +1 @@
calt.fea
+212
View File
@@ -0,0 +1,212 @@
languagesystem DFLT dflt;
languagesystem latn dflt;
lookup lookup_0 {
sub zero by zero.num;
sub one by one.num;
sub two by two.num;
sub three by three.num;
sub four by four.num;
sub five by five.num;
sub six by six.num;
sub seven by seven.num;
sub eight by eight.num;
sub nine by nine.num;
sub slash by fraction;
sub fraction by fraction.afrc;
} lookup_0;
lookup lookup_1 {
sub zero by zero.den;
sub one by one.den;
sub two by two.den;
sub three by three.den;
sub four by four.den;
sub five by five.den;
sub six by six.den;
sub seven by seven.den;
sub eight by eight.den;
sub nine by nine.den;
sub slash by fraction;
} lookup_1;
lookup lookup_2 {
sub L periodcentered by Ldot;
sub l periodcentered by ldot;
} lookup_2;
feature case {
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;
feature dnom {
sub zero by zero.den;
sub one by one.den;
sub two by two.den;
sub three by three.den;
sub four by four.den;
sub five by five.den;
sub six by six.den;
sub seven by seven.den;
sub eight by eight.den;
sub nine by nine.den;
} dnom;
feature frac {
lookup frac0 {
sub [zero one two three four five six seven eight nine] slash' lookup lookup_0 [zero one two three four five six seven eight nine] ;
} frac0;
lookup frac1 {
ignore sub [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] [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] fraction' ;
ignore sub fraction' [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] [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] ;
sub [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] fraction' lookup lookup_0 [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] ;
} frac1;
lookup frac2 {
sub [zero one two three four five six seven eight nine]' lookup lookup_0 fraction.afrc ;
sub fraction.afrc [zero one two three four five six seven eight nine]' lookup lookup_1 ;
} 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 locl {
script latn;
language CAT ;
sub l' lookup lookup_2 periodcentered' lookup lookup_2 l ;
sub L' lookup lookup_2 periodcentered' lookup lookup_2 L ;
} locl;
feature numr {
sub zero by zero.num;
sub one by one.num;
sub two by two.num;
sub three by three.num;
sub four by four.num;
sub five by five.num;
sub six by six.num;
sub seven by seven.num;
sub eight by eight.num;
sub nine by nine.num;
} numr;
feature rupa {
sub R p by R_p;
} rupa;
feature ss01 {
sub registered by registered.alt;
} ss01;
feature salt {
lookup salt0 {
sub registered by registered.alt;
} salt0;
lookup salt1 {
sub colon by colon.alt;
} salt1;
lookup salt2 {
sub bullet by bullet.alt;
} salt2;
lookup salt3 {
sub asterisk by asterisk.alt;
} salt3;
lookup salt4 {
sub zero by zero.alt;
} salt4;
lookup salt5 {
sub underscore by underscore.alt;
} salt5;
lookup salt6 {
sub [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] slash' lookup lookup_1 [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] ;
} salt6;
} salt;
feature sinf {
sub zero by zero.inf;
sub one by one.inf;
sub two by two.inf;
sub three by three.inf;
sub four by four.inf;
sub five by five.inf;
sub six by six.inf;
sub seven by seven.inf;
sub eight by eight.inf;
sub nine by nine.inf;
} sinf;
feature ss03 {
sub colon by colon.alt;
} ss03;
feature ss04 {
sub bullet by bullet.alt;
} ss04;
feature ss05 {
sub asterisk by asterisk.alt;
} ss05;
feature ss07 {
sub zero by zero.alt;
} ss07;
feature ss08 {
sub underscore by underscore.alt;
} ss08;
feature ss09 {
sub [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] slash' lookup lookup_1 [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] ;
} ss09;
feature subs {
sub zero by zero.inf;
sub one by one.inf;
sub two by two.inf;
sub three by three.inf;
sub four by four.inf;
sub five by five.inf;
sub six by six.inf;
sub seven by seven.inf;
sub eight by eight.inf;
sub nine by nine.inf;
} subs;
feature subs {
sub zero by zero.sup;
sub one by one.sup;
sub two by two.sup;
sub three by three.sup;
sub four by four.sup;
sub five by five.sup;
sub six by six.sup;
sub seven by seven.sup;
sub eight by eight.sup;
sub nine by nine.sup;
} subs;
include(calt.fea);
+36
View File
@@ -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);
});
});
});
});
Binary file not shown.

After

Width:  |  Height:  |  Size: 81 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 175 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 33 KiB

+308 -241
View File
@@ -1,171 +1,291 @@
const Promise = require('bluebird');
const fs = Promise.promisifyAll(require('fs'));
// @ts-nocheck
const fs = require('fs');
const os = require('os');
if (!os.EOL) {
os.EOL = process.platform === 'win32' ? '\r\n' : '\n';
}
const calt = require('./calt');
const xpath = require('xpath');
const { DOMParser, XMLSerializer } = require('xmldom');
const format = require('xml-formatter');
let fontName;
let ligFontName;
const regEx = /\.liga$/;
const regExBlankLines = /^(?=\n)$|^\s*/gm;
const regExWhitespace = /^\s+$/;
const NodeType = {};
NodeType.TEXT_NODE = 3;
async function main() {
let dom;
let italicsHack = false;
function main() {
fontName = process.argv[2];
italicsHack =
fontName.includes('Italic') && process.argv[3] !== '--italics-hack-off';
ligFontName = fontName.split('-').join('Lig-');
const srcFileName = `./original/${fontName}.ttx`;
const dstFileName = `./build/${ligFontName}.ttx`;
console.log(`Reading original font file ${srcFileName}`);
const xml = await fs.readFileAsync(srcFileName, 'utf-8');
const dom = new DOMParser().parseFromString(xml);
const xml = fs.readFileSync(srcFileName, 'utf-8');
dom = new DOMParser().parseFromString(xml);
try {
await processPatch('names', patchNames, dom);
await processPatch('glyphs', patchGlyphs, dom);
await processPatch('gpos', patchGpos, dom);
await processPatch('gsub', patchGsub, dom);
await processPatch('hmtx', patchHmtx, dom);
//await processPatch('lookup', patchLookup, dom);
await processPatch('charstrings', patchCharStrings, dom);
} catch (err) {
console.log(err);
}
const profiles = getProfiles();
// process settings (there may be more than one font to build)
profiles.forEach((profile) => buildFont(profile, { italicsHack }));
console.log(`Writing ligature font file ${dstFileName}`);
await fs.writeFileAsync(dstFileName, format(serialize(dom)));
console.log('Done');
}
async function loadConfigAsync(name) {
const buildFont = (profile, options) => {
// add suffix to dstFileName if present
const dstFileName = `./build/${ligFontName}${profile.suffixWithLeadingHyphen}.ttx`;
console.log(
`Building ligature font file ${dstFileName} name = ${profile.name}`
);
const ligatures = sortLigatures(
fs
.readdirSync(`./ligature/${ligFontName}/glyphs`)
.filter((file) => /\.xml$/.test(file))
.map((file) => file.replace('.xml', ''))
)
.filter((name) => !/\d+\.liga$/.test(name)) // skip alternates (ends with .#)
.filter((name) => filterLigatures(name, profile.ligatures))
.map((name) => mapLigatures(name, profile.ligatures))
.filter((entry) => filterGlyphsExists(entry));
const ligaturesWithLIG = ligatures;
//[...ligatures, { name: 'LIG', glyph: 'LIG' }];
processPatch('names', patchNames, dom, ligatures, profile);
processPatch('charstrings', patchCharStrings, dom, ligaturesWithLIG);
processPatch('glyphs', patchGlyphs, dom, ligaturesWithLIG);
processPatch('hmtx', patchHmtx, dom);
const feature = calt.gencalt(ligatures);
fs.writeFileSync('./features/calt.fea', feature);
console.log(`Writing ligature font file ${dstFileName}`);
fs.writeFileSync(dstFileName, format(serialize(dom)));
};
const getProfiles = () => {
const profilePath = './original/profiles.ini';
// return default profiles if profile doesn't exist
if (!fs.existsSync(profilePath)) {
return [
{
name: 'default',
suffix: '',
suffixWithLeadingSpace: '',
suffixWithLeadingHyphen: '',
ligatures: [],
},
];
}
const profiles = [];
let profile = null;
const content = fs.readFileSync(profilePath, 'utf-8');
content
.split(/\r|\r\n|\n/g)
.filter((line) => /^[#]/.test(line) === false && line.length > 0)
.forEach((line) => {
const ch = line.trim()[0];
if (ch === '[') {
let name = line.substr(1, line.indexOf(']') - 1);
profile = {
name,
suffix: name === 'default' ? '' : name,
suffixWithLeadingSpace: name === 'default' ? '' : ' ' + name,
suffixWithLeadingHyphen: name === 'default' ? '' : '-' + name,
ligatures: [],
};
profiles.push(profile);
} else {
if (!profile) {
throw new Error('You must provide a profile name in []');
}
profile.ligatures.push(line);
}
});
return profiles;
};
const filterLigatures = (name, mappings) => {
// loop through mappings and return if name applies or not
// skip if setting is !name
return mappings.filter((entry) => entry === '!' + name).length === 0;
};
const mapLigatures = (name, mappings) => {
let mapping = { name, glyph: name };
mappings.forEach((entry) => {
const [val1, val2] = entry.split('=');
// handle lig=altliga
if (val1 === name) {
mapping.glyph = val2;
} else if (val2 === name) {
mapping.name = val1;
}
});
return mapping;
};
const filterGlyphsExists = ({ glyph }) => {
const exists = fs.existsSync(`./ligature/${ligFontName}/glyphs/${glyph}.xml`);
return exists;
};
const sortLigatures = (ligatures) => {
// sort by most glyphs then alphabetically
const sorted = ligatures
.map((ligature) => {
return { count: ligature.split('_').length + 1, ligature: ligature };
})
.sort(
(a, b) =>
-compareProperty(a.count, b.count) || // sort by count descending
compareProperty(a.ligature, b.ligature) // then by ligature alphabetically
)
.map((entry) => entry.ligature);
return sorted;
};
const compareProperty = (a, b) => {
if (typeof a === 'number') {
return a || b ? (!a ? -1 : !b ? 1 : a === b ? 0 : a < b ? -1 : 1) : 0;
} else {
return a || b ? (!a ? -1 : !b ? 1 : a.localeCompare(b)) : 0;
}
};
const loadXml = (name) => {
const fileName = `./ligature/${ligFontName}/${name}.xml`;
const xml = await fs.readFileAsync(fileName, 'utf-8');
const xml = fs.readFileSync(fileName, 'utf-8');
return new DOMParser().parseFromString(xml);
}
};
async function processPatch(name, patchFunc, dom) {
const processPatch = (name, patchFunc, dom, ligatures, profile, options) => {
console.log(`Patching ${name}`);
await patchFunc(dom);
}
patchFunc(dom, ligatures, profile, options);
};
async function patchNames(dom) {
const configDom = await loadConfigAsync('names');
const PlatformId = {
mac: 1,
win: 3,
};
const names = xpath.select('/name/namerecord', configDom);
const targetName = xpath.select('/ttFont/name', dom, true);
const NameId = {
familyName: 1,
fontStyle: 2,
uniqueId: 3,
fullName: 4,
version: 5,
postscriptName: 6,
windowsFamilyName: 16,
fontStyleName: 17,
};
// get font and family name
const familyName = getTextNode(
configDom,
'/name/namerecord[@nameID="1" and @platformID="1"]'
);
const fullName = getTextNode(
configDom,
'/name/namerecord[@nameID="4" and @platformID="1"]'
const patchNames = (dom, ligatures, profile) => {
const names = JSON.parse(
fs.readFileSync(`./ligature/${ligFontName}/names.json`)
);
const [name, style] = names.fontName.split('-');
const [familyStyle, fullNameStyleTry] = names.fontStyle.split(' ');
let fullNameStyleTemp;
if (fullNameStyleTry) {
fullNameStyleTemp = fullNameStyleTry;
} else {
fullNameStyleTemp = '';
}
const fullNameStyle = fullNameStyleTemp;
const fontName = `${name}${profile.suffixWithLeadingHyphen}-${style}`;
const familyNamePlat = `${names.familyName}${profile.suffixWithLeadingSpace}`;
const familyName = `${familyNamePlat} ${familyStyle}`;
const fullName = `${familyName} ${fullNameStyle}`;
const uniqueId = `${names.foundry}: ${fullName}: ${names.version}`;
// patch CFFFont
const cffFont = xpath.select('/ttFont/CFF/CFFFont', dom, true);
cffFont.setAttribute('name', ligFontName);
setAttribute(cffFont, 'FullName', 'value', fullName);
setAttribute(cffFont, 'FamilyName', 'value', familyName);
setAttribute(cffFont, 'FamilyName', 'value', familyNamePlat);
// update existing names with new names
names.forEach(node => {
const nameId = node.getAttribute('nameID');
const platformId = node.getAttribute('platformID');
// mac family name does not include style
updateName(PlatformId.mac, NameId.familyName, familyNamePlat);
updateName(PlatformId.mac, NameId.fontStyle, names.fontStyle);
updateName(PlatformId.mac, NameId.uniqueId, uniqueId);
updateName(PlatformId.mac, NameId.fullName, fullName);
updateName(PlatformId.mac, NameId.postscriptName, fontName);
updateName(PlatformId.mac, NameId.windowsFamilyName, familyNamePlat);
updateName(PlatformId.mac, NameId.fontStyleName, names.fontStyle);
// search for namerecord in target dom and replace with this one or append node
const target = xpath.select(
`/ttFont/name/namerecord[@nameID="${nameId}" and @platformID="${platformId}"]`,
dom,
true
);
if (target) {
target.parentNode.replaceChild(node, target);
} else {
targetName.appendChild(node);
}
});
}
// windows family name includes style
updateName(PlatformId.win, NameId.familyName, familyName);
updateName(PlatformId.win, NameId.fontStyle, names.windowsFontStyle);
updateName(PlatformId.win, NameId.uniqueId, uniqueId);
updateName(PlatformId.win, NameId.fullName, fullName);
updateName(PlatformId.win, NameId.postscriptName, fontName);
updateName(PlatformId.win, NameId.windowsFamilyName, familyNamePlat);
updateName(PlatformId.win, NameId.fontStyleName, names.fontStyle);
};
async function patchGlyphs(dom) {
const configDom = await loadConfigAsync('../glyphs');
const updateName = (platformId, nameId, value) => {
// search for namerecord in target dom and replace with this one or append node
const target = xpath.select(
`/ttFont/name/namerecord[@nameID="${nameId}" and @platformID="${platformId}"]`,
dom,
true
);
if (target) {
target.childNodes[0].textContent = value;
}
};
const patchGlyphs = (dom, ligatures) => {
// get number of glyphs in target dom
const targetGlyphs = xpath.select('/ttFont/GlyphOrder', dom, true);
const glyphsCount = xpath.select('count(GlyphID)', targetGlyphs, true);
// only import glyphs specified
let n = glyphsCount;
// get ligature glyphs
const glyphs = xpath.select('/GlyphOrder/GlyphID', configDom);
glyphs.forEach(node => {
node.setAttribute('id', n++);
targetGlyphs.appendChild(node);
ligatures.forEach((ligature) => {
targetGlyphs.appendChild(
createElementWithAttributes('GlyphID', { id: n++, name: ligature.glyph })
);
});
// update glyph count
setAttribute(dom, '/ttFont/maxp/numGlyphs', 'value', n);
}
async function patchGpos(dom) {
const newGpos = await loadConfigAsync('gpos');
const oldGpos = xpath.select('/ttFont/GPOS', dom, true);
dom.documentElement.replaceChild(newGpos, oldGpos);
}
async function patchGsub(dom) {
const newGsub = await loadConfigAsync('gsub');
// loop through Substituion/Ligature nodes and remap chars
remap(newGsub, dom, '//Substitution', 'out');
remap(newGsub, dom, '//Ligature', 'glyph');
const oldGsub = xpath.select('/ttFont/GSUB', dom, true);
dom.documentElement.replaceChild(newGsub, oldGsub);
}
const remap = (patchDom, cmapDom, path, attr) => {
const cmap = [];
let nodes = xpath.select(path, patchDom);
nodes.forEach(n => {
const out = n.getAttribute(attr);
if (out.startsWith('uni')) {
// get cmap entry
const code = '0x' + out.replace(/uni0*/g, '').toLowerCase();
let name = cmap[code];
if (!name) {
const map = xpath.select(
`/ttFont/cmap/cmap_format_4/map[@code="${code}"]`,
cmapDom,
true
);
name = map == null ? out : map.getAttribute('name');
cmap[code] = name;
}
n.setAttribute(attr, name);
}
});
};
async function patchHmtx(dom) {
const hmtxDom = await loadConfigAsync('hmtx');
const targetHmtx = xpath.select('/ttFont/hmtx', dom, true);
const patchGsub = (dom, ligatures, options) => {
// don't patch if no ligatures other than LIG
if (ligatures.length <= 1) return;
gsub.initGsubTables(dom, options);
const mtx = xpath.select('/hmtx/mtx', hmtxDom);
mtx.forEach(node => targetHmtx.appendChild(node));
ligatures.forEach((ligature) => {
// build gsub tables
gsub.buildGsubTables(dom, ligature, options);
});
gsub.finalizeGsubTables();
};
const patchHmtx = (dom) => {
const mtxCount = xpath.select('count(/ttFont/hmtx/mtx)', dom, true);
setAttribute(dom, '/ttFont/hhea/numberOfHMetrics', 'value', mtxCount);
const configDom = await loadConfigAsync('config');
const configDom = loadXml('config');
copyConfigAttribute(dom, configDom, '/ttFont/head/xMin', 'value');
copyConfigAttribute(dom, configDom, '/ttFont/head/yMin', 'value');
copyConfigAttribute(dom, configDom, '/ttFont/head/xMax', 'value');
@@ -179,159 +299,104 @@ async function patchHmtx(dom) {
'/ttFont/CFF/CFFFont/Private/nominalWidthX',
'value'
);
}
async function patchLookup(dom) {
const configDom = await loadConfigAsync('../lookup');
const featureList = xpath.select('/ttFont/GSUB/FeatureList', dom, true);
const featuresCount = xpath.select(
'count(/ttFont/GSUB/FeatureList/FeatureRecord)',
dom,
true
);
const featureRecord = dom.createElement('FeatureRecord');
featureRecord.setAttribute('index', featuresCount);
const featureTag = dom.createElement('FeatureTag');
featureTag.setAttribute('value', 'liga');
const feature = dom.createElement('Feature');
featureRecord.appendChild(featureTag);
featureRecord.appendChild(feature);
featureList.appendChild(featureRecord);
const lookupCount = xpath.select(
'count(/ttFont/GSUB/LookupList/Lookup)',
dom,
true
);
const lookupListIndex = dom.createElement('LookupListIndex');
lookupListIndex.setAttribute('index', '0');
lookupListIndex.setAttribute('value', lookupCount);
feature.appendChild(lookupListIndex);
// helper function for adding feature to ScriptRecord
const addFeature = (scriptRecord, featureRecord, lang) => {
if (!lang) return;
const index = featureRecord.getAttribute('index');
if (xpath.select(`FeatureIndex[@value="${index}"]`, lang, true)) return;
const count = xpath.select('count(FeatureIndex)', lang, true);
const featureIndex = dom.createElement('FeatureIndex');
featureIndex.setAttribute('index', count);
featureIndex.setAttribute('value', index);
lang.appendChild(featureIndex);
};
// nead to add feature to ScriptList
const scriptList = xpath.select('/ttFont/GSUB/ScriptList', dom, true);
const scriptRecords = xpath.select('ScriptRecord', scriptList);
scriptRecords.forEach(node => {
// check for feature in DefaultLangSys
addFeature(
node,
featureRecord,
xpath.select('Script/DefaultLangSys', node, true)
);
// add features to any other languages
xpath
.select('Script/LangSysRecord/LangSys', node)
.forEach(lang => addFeature(node, featureRecord, lang));
});
// finally add LigatureSubst to Lookup
const lookupList = xpath.select('/ttFont/GSUB/LookupList', dom, true);
const newLookup = xpath.select('/LookupList/Lookup', configDom, true);
newLookup.setAttribute('index', lookupCount);
lookupList.appendChild(newLookup);
}
async function patchCharStrings(dom) {
const configDom = await loadConfigAsync('charstrings');
const nameDom = await loadConfigAsync('names');
// get font and family name
const familyName = getTextNode(
nameDom,
'/name/namerecord[@nameID="1" and @platformID="1"]'
);
const fullName = getTextNode(
nameDom,
'/name/namerecord[@nameID="4" and @platformID="1"]'
);
};
const patchCharStrings = (dom, ligatures) => {
// patch CFFFont
const cffFont = xpath.select('/ttFont/CFF/CFFFont', dom, true);
cffFont.setAttribute('name', ligFontName);
setAttribute(cffFont, 'FullName', 'value', fullName);
setAttribute(cffFont, 'FamilyName', 'value', familyName);
const charStrings = xpath.select('/CharStrings/CharString', configDom);
const targetHmtx = xpath.select('/ttFont/hmtx', dom, true);
const targetCmaps = xpath.select('/ttFont/cmap/cmap_format_4', dom);
const targetCharStrings = xpath.select('CharStrings', cffFont, true);
const targetSubrs = xpath.select(
'/ttFont/CFF/CFFFont/Private/Subrs',
dom,
true
);
const targetGsubrs = xpath.select('/ttFont/CFF/GlobalSubrs', dom, true);
const fingerprints = {};
ligatures.forEach((ligature) => {
console.log(
`* ${ligature.name}${
ligature.name === ligature.glyph ? '' : ' => ' + ligature.glyph
}`
);
const glyphDom = loadXml(`glyphs/${ligature.glyph}`).documentElement;
const node = xpath.select('/Glyph/CharString', glyphDom, true);
node.setAttribute('name', ligature.glyph);
const subrs = {
map: [],
source: await loadConfigAsync('subrs'),
target: xpath.select('/ttFont/CFF/CFFFont/Private/Subrs', dom, true)
};
const gsubrs = {
map: [],
source: await loadConfigAsync('gsubrs'),
target: xpath.select('/ttFont/CFF/GlobalSubrs', dom, true)
};
const subrs = {
sourcePath: '/Glyph/Subrs',
target: targetSubrs,
};
const gsubrs = {
sourcePath: '/Glyph/GlobalSubrs',
target: targetGsubrs,
};
patchCharStringSubrs(glyphDom, node, fingerprints, subrs, gsubrs);
charStrings.forEach(node => {
patchCharStringSubrs(node, subrs, gsubrs);
targetCharStrings.appendChild(node);
targetHmtx.appendChild(
createElementWithAttributes('mtx', {
name: ligature.glyph,
width: glyphDom.getAttribute('width'),
lsb: glyphDom.getAttribute('lsb'),
})
);
const code = glyphDom.getAttribute('code');
if (code) {
Array.from(targetCmaps).forEach((node) => {
node.appendChild(
createElementWithAttributes('map', {
code,
name: ligature.glyph,
})
);
});
}
});
}
};
const patchCharStringSubrs = (node, subrs, gsubrs) => {
const patchCharStringSubrs = (glyphDom, node, fingerprints, subrs, gsubrs) => {
// check for callsubr/callgsubr
const lines = node.childNodes[0].textContent.split(/\r|\r\n|\n/g);
const newLines = [];
let patched = false;
lines.forEach(line => {
const matches = line.match(/(.*?)(-?\d+) (callsubr|callgsubr)$/);
lines.forEach((line) => {
if (line.trim().length === 0) return;
const matches = line.match(/(.*?)\{([0-9a-z]+)\} (callsubr|callgsubr)$/);
if (matches != null) {
const { map, source, target } =
matches[3] === 'callsubr' ? subrs : gsubrs;
const index = matches[2];
let newIndex = 0;
if (!map[index]) {
// find subr in source dom and copy to target dom
const srcIndex = parseInt(index) + 107;
const { sourcePath, target } = matches[3] === 'callsubr' ? subrs : gsubrs;
const fingerprint = matches[2];
let newIndex = fingerprints[fingerprint];
if (!newIndex) {
const srcSubr = xpath.select(
`//CharString[@index="${srcIndex}"]`,
source,
`/${sourcePath}/CharString[@fingerprint="${fingerprint}"]`,
glyphDom,
true
);
// patch up source in case it also has any callsubrs
patchCharStringSubrs(srcSubr, subrs, gsubrs);
// append subr to target dom and get new index
newIndex = xpath.select('count(CharString)', target, true);
srcSubr.setAttribute('index', newIndex);
target.appendChild(srcSubr);
const clone = srcSubr.cloneNode(true);
clone.setAttribute('index', newIndex);
target.appendChild(clone);
// add new index to map and rewrite call
newIndex = newIndex - 107;
map[index] = newIndex;
} else {
newIndex = map[index];
fingerprints[fingerprint] = newIndex;
// patch up source in case it also has any callsubrs
patchCharStringSubrs(glyphDom, clone, fingerprints, subrs, gsubrs);
}
// rewrite line with new subr index
line = `${matches[1]}${newIndex} ${matches[3]}`;
patched = true;
}
newLines.push(line);
});
if (patched) {
node.childNodes[0].textContent = newLines.join(os.EOL);
}
node.childNodes[0].textContent = newLines.join(os.EOL);
};
const setAttribute = (parent, path, name, value) => {
@@ -344,21 +409,23 @@ const copyConfigAttribute = (dom, configDom, path, name) => {
setAttribute(dom, path, name, value);
};
const getTextNode = (dom, path) => {
var node = xpath.select(path, dom, true);
return node && node.childNodes.length
? node.childNodes[0].nodeValue.trim()
: '';
const createElementWithAttributes = (tagName, attributes) => {
const element = dom.createElement(tagName);
Object.entries(attributes).forEach((attribute) => {
element.setAttribute(attribute[0], attribute[1]);
});
return element;
};
const serialize = dom =>
new XMLSerializer().serializeToString(dom, false, node => {
//const dump = dom => console.log(serialize(dom));
const serialize = (dom) =>
new XMLSerializer().serializeToString(dom, false, (node) => {
if (node.nodeType === NodeType.TEXT_NODE) {
if (regExWhitespace.test(node.data)) return null;
const data = node.data
.split(/\r|\r\n|\n/g)
.filter(s => /\S+/.test(s))
.map(s => s.replace(/^\s+/g, ''))
.filter((s) => /\S+/.test(s))
.map((s) => s.replace(/^\s+/g, ''))
.join(os.EOL);
return node.ownerDocument.createTextNode(data);
@@ -1,281 +0,0 @@
<CharStrings>
<CharString name="ampersand_ampersand.liga">
-107 -12 67 501 76 hstemhm
108 77 -4 80 251 77 -4 80 hintmask 11100100
880 169 rmoveto
-33 callgsubr
-66 callsubr
hintmask 11011000
-88 -56 -45 -63 -75 vvcurveto
-3 vlineto
-12 15 -12 14 -12 13 -33 callgsubr
-66 callsubr
hintmask 11100100
-7 callgsubr
-33 57 -74 133 -4 rrcurveto
7 hlineto
64 64 34 77 51 hvcurveto
28 -34 31 -37 32 -41 65 51 rcurveline
-41 50 -37 43 -33 38 rrcurveto
-611 -114 rmoveto
-51 callgsubr
hintmask 11101000
404 hmoveto
-51 callgsubr
endchar
</CharString>
<CharString name="bar_bar.liga">
-107 704 -20 hstem
312 75 325 75 vstem
387 710 -14 callgsubr
400 892 -14 callgsubr
endchar
</CharString>
<CharString name="bar_greater.liga">
-107 704 -20 hstem
287 75 449 74 vstem
362 710 -14 callgsubr
523 440 rlineto
69 vlineto
-74 -40 rmoveto
-449 -374 rlineto
705 vlineto
449 -321 rlineto
endchar
</CharString>
<CharString name="equal_equal.liga">
-107 151 -25 callgsubr
944 vstem
1021 373 rmoveto
-9 callsubr
-944 -69 hlineto
943 -222 rmoveto
-9 callsubr
-944 -69 hlineto
endchar
</CharString>
<CharString name="equal_equal_equal.liga">
-11 callgsubr
495 -4 callsubr
1493 -222 -4 callsubr
1493 -222 -4 callsubr
endchar
</CharString>
<CharString name="equal_equal_greater.liga">
443 -1 -21 173 -9 callgsubr
hstem
1498 74 vstem
1245 16 callgsubr
124 -102 rlineto
-1244 -69 1328 hlineto
92 -76 rlineto
-10 vlineto
-81 -67 rlineto
-1339 -69 1256 hlineto
-140 -116 -32 callgsubr
endchar
</CharString>
<CharString name="equal_greater.liga">
-107 -1 -21 173 -9 callgsubr
hstem
948 74 vstem
695 16 callgsubr
124 -102 rlineto
-694 -69 778 hlineto
92 -76 rlineto
-10 vlineto
-81 -67 rlineto
-789 -69 706 hlineto
-140 -116 -32 callgsubr
endchar
</CharString>
<CharString name="exclam_equal.liga">
-107 151 -25 callgsubr
944 vstem
646 373 rmoveto
375 hlineto
-9 callsubr
-340 hlineto
132 252 -69 32 -149 -284 rlineto
-518 -69 482 hlineto
-81 -153 rlineto
-401 -69 365 hlineto
-163 -311 71 -29 178 340 rlineto
492 hlineto
-9 callsubr
-457 hlineto
endchar
</CharString>
<CharString name="exclam_equal_equal.liga">
-11 callgsubr
273 rmoveto
-9 callsubr
-683 hlineto
81 153 rlineto
601 hlineto
-9 callsubr
-566 hlineto
68 130 -69 32 -85 -162 rlineto
-842 -69 806 hlineto
-81 -153 rlineto
-725 -69 689 hlineto
-80 -153 rlineto
-609 -69 573 hlineto
-111 -211 71 -29 126 240 rlineto
834 hlineto
-9 callsubr
-799 hlineto
80 153 rlineto
endchar
</CharString>
<CharString name="greater_equal.liga">
-107 634 -20 88 -20 hstem
741 114 vstem
187 145 rmoveto
35 -67 633 280 rlineto
69 vlineto
-627 275 -37 -68 550 -237 rlineto
-10 vlineto
114 -191 rmoveto
-668 -291 35 -67 633 280 rlineto
endchar
</CharString>
<CharString name="hyphen_greater.liga">
-107 -7 callsubr
944 vstem
695 16 callgsubr
264 -217 rlineto
-834 -69 835 hlineto
-269 -223 -32 callgsubr
endchar
</CharString>
<CharString name="hyphen_hyphen.liga">
-107 258 69 hstem
181 737 vstem
492 258 rmoveto
12 callgsubr
731 hmoveto
12 callgsubr
endchar
</CharString>
<CharString name="hyphen_hyphen_greater.liga">
443 -7 callsubr
1494 vstem
1245 16 callgsubr
264 -217 rlineto
-1384 -69 1385 hlineto
-269 -223 -32 callgsubr
endchar
</CharString>
<CharString name="less_bar.liga">
-107 704 -20 hstem
216 75 448 75 vstem
739 704 rmoveto
-523 -378 rlineto
-69 vlineto
523 -439 rlineto
75 892 hlineto
-523 -423 rmoveto
10 vlineto
448 317 rlineto
-701 vlineto
endchar
</CharString>
<CharString name="less_equal.liga">
-107 702 -20 hstem
245 114 vstem
913 145 rmoveto
-554 242 rlineto
10 vlineto
550 237 -37 68 -627 -275 rlineto
-69 vlineto
633 -280 rlineto
-633 118 rmoveto
-78 vlineto
633 -280 35 67 rlineto
endchar
</CharString>
<CharString name="less_equal_equal.liga">
443 -1 -21 173 -25 callgsubr
75 vstem
153 287 rmoveto
10 vlineto
92 76 rlineto
1326 hlineto
-9 callsubr
-1244 hlineto
124 103 -45 callgsubr
-139 116 rlineto
1254 hlineto
-9 callsubr
-1338 hlineto
endchar
</CharString>
<CharString name="less_exclam_hyphen_hyphen.liga">
993 -1 -21 22 110 148 69 hstemhm
816 113.5 hintmask 01110000
852 -18 callsubr
-400 311 rmoveto
-45 58 -329 -277 rlineto
-69 vlineto
hintmask 10110000
332 -279 46 57 -268 223 rlineto
521 hlineto
6 69 rlineto
-526 hlineto
860 hmoveto
-69 1067 vlineto
6 69 rlineto
hintmask 01110000
-1307 -327 10 callgsubr
</CharString>
<CharString name="less_hyphen.liga">
-107 -7 callsubr
944 vstem
1022 327 rmoveto
-833 hlineto
263 218 -45 callgsubr
-268 223 rlineto
828 hlineto
endchar
</CharString>
<CharString name="less_hyphen_hyphen.liga">
443 -7 callsubr
1494 vstem
1572 327 rmoveto
-1383 hlineto
263 218 -45 callgsubr
-268 223 rlineto
1378 hlineto
endchar
</CharString>
<CharString name="plus_plus.liga">
-107 259 68 hstem
301 73 353 73 vstem
800 327 rmoveto
187 -73 -187 -353 9 callgsubr
187 353 -187 73 187 176 vlineto
1 68 rlineto
endchar
</CharString>
</CharStrings>
+79 -11
View File
@@ -1,52 +1,120 @@
<ttFont>
<head>
<!-- Most of this table will be recalculated by the compiler -->
<tableVersion value="1.0"/>
<fontRevision value="1.002"/>
<checkSumAdjustment value="0x1cc640f7"/>
<magicNumber value="0x5f0f3cf5"/>
<flags value="00000000 00000011"/>
<unitsPerEm value="1000"/>
<created value="Mon Oct 16 12:43:41 2017"/>
<modified value="Mon Oct 16 12:43:41 2017"/>
<xMin value="-339"/>
<xMin value="-1564"/>
<yMin value="-288"/>
<xMax value="2122"/>
<xMax value="630"/>
<yMax value="1144"/>
<macStyle value="00000000 00000000"/>
<lowestRecPPEM value="3"/>
<fontDirectionHint value="2"/>
<indexToLocFormat value="0"/>
<glyphDataFormat value="0"/>
</head>
<hhea>
<tableVersion value="0x00010000"/>
<ascent value="960"/>
<descent value="-240"/>
<lineGap value="0"/>
<advanceWidthMax value="2200"/>
<minLeftSideBearing value="-339"/>
<advanceWidthMax value="600"/>
<minLeftSideBearing value="-1564"/>
<minRightSideBearing value="-80"/>
<xMaxExtent value="2122"/>
<xMaxExtent value="630"/>
<caretSlopeRise value="1"/>
<caretSlopeRun value="0"/>
<caretOffset value="0"/>
<reserved0 value="0"/>
<reserved1 value="0"/>
<reserved2 value="0"/>
<reserved3 value="0"/>
<metricDataFormat value="0"/>
<numberOfHMetrics value="454"/>
<numberOfHMetrics value="466"/>
</hhea>
<CFF>
<CFFFont>
<FontBBox value="-339 -288 2122 1144"/>
<FontBBox value="-1564 -288 630 1144"/>
</CFFFont>
</CFF>
<CFF>
<CFFFont>
<Private>
<nominalWidthX value="1207"/>
<nominalWidthX value="107"/>
</Private>
</CFFFont>
</CFF>
@@ -0,0 +1,7 @@
<Glyph name="LIG" lsb="0" width="550">
<CharString>
endchar
</CharString>
<Subrs/>
<GlobalSubrs/>
</Glyph>
@@ -0,0 +1,7 @@
<Glyph name="ampersand.spacer" lsb="0" width="600">
<CharString>
endchar
</CharString>
<Subrs/>
<GlobalSubrs/>
</Glyph>
@@ -0,0 +1,41 @@
<Glyph name="ampersand_ampersand.liga" lsb="-432" width="550">
<CharString>
-12 67 501 76 hstemhm
-269 80 227 77 -4 80 hintmask 11110000
316 169 rmoveto
33 59 32 79 22 89 -70 9 rcurveline
-14 -68 -21 -66 -23 -54 rrcurveto
-119 136 -55 59 52 vvcurveto
54 42 46 163 -8 vhcurveto
-6 76 rlineto
-213 4 -66 -91 -86 vvcurveto
-43 20 -40 40 -52 vhcurveto
-79 -50 -44 -56 -8 -65 -14 16 rcurveline
33 59 32 79 22 89 -70 9 rcurveline
-14 -68 -21 -66 -23 -54 rrcurveto
-119 136 -55 59 52 vvcurveto
54 42 46 163 -8 vhcurveto
-6 76 rlineto
-213 4 -66 -91 -86 vvcurveto
-43 20 -40 40 -52 vhcurveto
-88 -56 -45 -63 -75 vvcurveto
-80 49 -62 95 64 64 34 77 51 vhcurveto
22 -27 47 -52 67 -22 rrcurveto
-6 17 20 -4 23 hhcurveto
64 -1 69 35 51 77 28 -34 31 -37 32 -41 65 51 rcurveline
-41 50 -37 43 -33 38 rrcurveto
-587 -114 rmoveto
-55 -29 39 53 47 28 49 59 42 hvcurveto
32 -38 41 -46 48 -57 rrcurveto
-61 -39 -43 -28 -42 hhcurveto
380 hmoveto
-55 -29 39 53 hvcurveto
hintmask 11101000
47 28 49 59 42 vhcurveto
32 -38 41 -46 48 -57 rrcurveto
-61 -39 -43 -28 -42 hhcurveto
endchar
</CharString>
<Subrs/>
<GlobalSubrs/>
</Glyph>
@@ -0,0 +1,7 @@
<Glyph name="bar.spacer" lsb="0" width="600">
<CharString>
endchar
</CharString>
<Subrs/>
<GlobalSubrs/>
</Glyph>
@@ -0,0 +1,14 @@
<Glyph name="bar_bar.liga" lsb="-211" width="550">
<CharString>
-211 75 275 75 vstem
-136 710 rmoveto
-75 -6 rlineto
-886 75 vlineto
350 892 rmoveto
-75 -6 rlineto
-886 75 vlineto
endchar
</CharString>
<Subrs/>
<GlobalSubrs/>
</Glyph>
@@ -0,0 +1,17 @@
<Glyph name="bar_greater.liga" lsb="-261" width="550">
<CharString>
-261 75 468 74 vstem
-186 710 rmoveto
-75 -6 rlineto
-886 75 vlineto
541 440 rlineto
69 vlineto
-74 -40 rmoveto
-467 -376 rlineto
709 vlineto
467 -323 rlineto
endchar
</CharString>
<Subrs/>
<GlobalSubrs/>
</Glyph>
@@ -0,0 +1,7 @@
<Glyph name="colon.spacer" lsb="0" width="600">
<CharString>
endchar
</CharString>
<Subrs/>
<GlobalSubrs/>
</Glyph>
@@ -0,0 +1,23 @@
<Glyph name="colon_equal.liga" lsb="-297" width="550">
<CharString>
151 69 153 69 hstem
-297 658 vstem
-297 354 rmoveto
118 hlineto
2 117 rlineto
-119 hlineto
657 -98 rmoveto
1 69 rlineto
-424 -69 hlineto
-235 -245 rmoveto
118 hlineto
2 117 rlineto
-119 hlineto
657 -94 rmoveto
1 69 rlineto
-424 -69 hlineto
endchar
</CharString>
<Subrs/>
<GlobalSubrs/>
</Glyph>
@@ -0,0 +1,7 @@
<Glyph name="equal.spacer" lsb="0" width="600">
<CharString>
endchar
</CharString>
<Subrs/>
<GlobalSubrs/>
</Glyph>
@@ -0,0 +1,21 @@
<Glyph name="equal_equal.2.liga" lsb="-472" width="550">
<CharString>
151 69 153 69 hstem
-472 944 vstem
-49 373 rmoveto
1 69 rlineto
-424 -69 hlineto
943 hmoveto
1 69 rlineto
-414 -69 hlineto
-107 -222 rmoveto
1 69 rlineto
-424 -69 hlineto
943 hmoveto
1 69 rlineto
-414 -69 hlineto
endchar
</CharString>
<Subrs/>
<GlobalSubrs/>
</Glyph>
@@ -0,0 +1,15 @@
<Glyph name="equal_equal.liga" lsb="-472" width="550">
<CharString>
151 69 153 69 hstem
-472 944 vstem
471 373 rmoveto
1 69 rlineto
-944 -69 hlineto
943 -222 rmoveto
1 69 rlineto
-944 -69 hlineto
endchar
</CharString>
<Subrs/>
<GlobalSubrs/>
</Glyph>
@@ -0,0 +1,27 @@
<Glyph name="equal_equal_equal.2.liga" lsb="-1022" width="550">
<CharString>
151 69 153 69 hstem
-1022 1494 vstem
-579 373 rmoveto
1 69 rlineto
-444 -69 hlineto
968 hmoveto
1 69 rlineto
-444 -69 hlineto
968 hmoveto
1 69 rlineto
-444 -69 hlineto
-607 -222 rmoveto
1 69 rlineto
-444 -69 hlineto
968 hmoveto
1 69 rlineto
-444 -69 hlineto
968 hmoveto
1 69 rlineto
-444 -69 hlineto
endchar
</CharString>
<Subrs/>
<GlobalSubrs/>
</Glyph>
@@ -0,0 +1,18 @@
<Glyph name="equal_equal_equal.liga" lsb="-1022" width="550">
<CharString>
40 69 153 69 153 69 hstem
-1022 1494 cntrmask 11100000
471 484 rmoveto
1 69 rlineto
-1494 -69 hlineto
1493 -222 rmoveto
1 69 rlineto
-1494 -69 hlineto
1493 -222 rmoveto
1 69 rlineto
-1494 -69 hlineto
endchar
</CharString>
<Subrs/>
<GlobalSubrs/>
</Glyph>
@@ -0,0 +1,18 @@
<Glyph name="equal_equal_greater.liga" lsb="-1022" width="550">
<CharString>
151 69 153 69 hstem
-1022 394 1019 74 vstem
138 602 rmoveto
-47 -58 124 -102 rlineto
-1237 -69 1321 hlineto
92 -76 rlineto
-10 vlineto
-81 -67 rlineto
-1332 -69 1249 hlineto
-140 -116 45 -57 333 280 rlineto
69 vlineto
endchar
</CharString>
<Subrs/>
<GlobalSubrs/>
</Glyph>
@@ -0,0 +1,20 @@
<Glyph name="equal_greater.liga" lsb="-472" width="550">
<CharString>
151 69 153 69 hstemhm
-472 937 -74 74 hintmask 11100000
138 602 rmoveto
-47 -58 124 -102 rlineto
-687 -69 771 hlineto
hintmask 11010000
92 -76 rlineto
-10 vlineto
-81 -67 rlineto
hintmask 11100000
-782 -69 699 hlineto
-140 -116 45 -57 333 280 rlineto
69 vlineto
endchar
</CharString>
<Subrs/>
<GlobalSubrs/>
</Glyph>
@@ -0,0 +1,29 @@
<Glyph name="equal_less_less.liga" lsb="-1022" width="550">
<CharString>
151 69 153 69 hstemhm
-1022 1486 -688 75 235 75 hintmask 11011000
-149 297 rmoveto
299 248 -45 58 -191 -161 rlineto
hintmask 11100000
-936 -69 854 hlineto
hintmask 11011000
-56 -47 rlineto
-69 vlineto
44 -37 rlineto
hintmask 11100000
-842 -69 924 hlineto
206 -173 46 57 rlineto
hintmask 11011000
-303 252 rlineto
310 hmoveto
10 vlineto
299 248 -45 58 -329 -277 rlineto
-69 vlineto
332 -279 rlineto
hintmask 11100000
46 57 rlineto
endchar
</CharString>
<Subrs/>
<GlobalSubrs/>
</Glyph>
@@ -0,0 +1,7 @@
<Glyph name="exclam.spacer" lsb="0" width="600">
<CharString>
endchar
</CharString>
<Subrs/>
<GlobalSubrs/>
</Glyph>
@@ -0,0 +1,31 @@
<Glyph name="exclam_equal.liga" lsb="-472" width="550">
<CharString>
-189 915 -575 69 153 69 hstemhm
-472 944 -762 534 hintmask 00110000
76 373 rmoveto
395 hlineto
1 69 rlineto
-360 hlineto
hintmask 00101000
132 252 rlineto
hintmask 10001000
-69 32 rlineto
hintmask 00101000
-149 -284 rlineto
-498 -69 462 hlineto
hintmask 01101000
-81 -153 rlineto
-381 -69 345 hlineto
-163 -311 rlineto
hintmask 10001000
71 -29 rlineto
hintmask 01101000
178 340 rlineto
512 hlineto
1 69 rlineto
-477 hlineto
endchar
</CharString>
<Subrs/>
<GlobalSubrs/>
</Glyph>
@@ -0,0 +1,37 @@
<Glyph name="exclam_equal_equal.liga" lsb="-1022" width="550">
<CharString>
-189 915 -686 69 153 69 153 69 hstemhm
-1022 1494 -1012 534 cntrmask 01110000
hintmask 01111000
471 262 rmoveto
1 69 rlineto
-668 hlineto
80 153 rlineto
587 hlineto
1 69 rlineto
-552 hlineto
hintmask 01110100
74 141 rlineto
hintmask 10000100
-69 32 rlineto
hintmask 01110100
-91 -173 rlineto
-856 -69 820 hlineto
-80 -153 rlineto
-740 -69 703 hlineto
-80 -153 rlineto
-623 -69 587 hlineto
-105 -200 rlineto
hintmask 10000100
71 -29 rlineto
hintmask 01110100
120 229 rlineto
820 hlineto
1 69 rlineto
-785 hlineto
80 153 rlineto
endchar
</CharString>
<Subrs/>
<GlobalSubrs/>
</Glyph>
@@ -0,0 +1,7 @@
<Glyph name="greater.spacer" lsb="0" width="600">
<CharString>
endchar
</CharString>
<Subrs/>
<GlobalSubrs/>
</Glyph>
@@ -0,0 +1,17 @@
<Glyph name="greater_equal.2.liga" lsb="-308" width="600">
<CharString>
493 -141 69 390 69 hstem
-308 615 vstem
-308 95 rmoveto
-79 vlineto
615 302 rlineto
69 vlineto
-574 280 -37 -63 512 -247 rlineto
-10 vlineto
99 -488 rmoveto
69 -615 -69 vlineto
endchar
</CharString>
<Subrs/>
<GlobalSubrs/>
</Glyph>
@@ -0,0 +1,17 @@
<Glyph name="greater_equal.liga" lsb="-308" width="550">
<CharString>
138 77 103 69 hstem
-308 615 vstem
-308 95 rmoveto
31 -64 584 287 rlineto
69 vlineto
-574 280 -37 -63 512 -247 rlineto
-10 vlineto
99 -209 rmoveto
77 vlineto
-615 -300 31 -64 rlineto
endchar
</CharString>
<Subrs/>
<GlobalSubrs/>
</Glyph>
@@ -0,0 +1,32 @@
<Glyph name="greater_equal_greater.liga" lsb="-1013" width="550">
<CharString>
151 69 153 69 hstemhm
-1013 1478 -1174 74 1026 74 hintmask 11100000
138 602 rmoveto
-47 -58 124 -102 rlineto
-987 hlineto
-190 160 -47 -58 rlineto
hintmask 11010000
300 -247 rlineto
-10 vlineto
hintmask 11100000
-304 -252 45 -57 206 173 rlineto
989 hlineto
-140 -116 45 -57 333 280 rlineto
69 vlineto
hintmask 11001000
-74 -40 rmoveto
-81 -67 rlineto
-990 hlineto
hintmask 11010000
45 38 rlineto
69 vlineto
-55 46 rlineto
989 hlineto
hintmask 11001000
92 -76 rlineto
endchar
</CharString>
<Subrs/>
<GlobalSubrs/>
</Glyph>
@@ -0,0 +1,32 @@
<Glyph name="greater_greater_equal.liga" lsb="-1013" width="550">
<CharString>
151 69 153 69 hstemhm
-1013 1485 -1181 74 236 74 hintmask 11011000
-635 327 rmoveto
-327 275 -47 -58 300 -247 rlineto
-10 vlineto
hintmask 11100000
-304 -252 45 -57 rlineto
hintmask 11011000
333 280 rlineto
310 hmoveto
69 vlineto
-55 46 rlineto
hintmask 11100000
851 hlineto
1 69 rlineto
-934 hlineto
-190 160 -47 -58 rlineto
hintmask 11001000
300 -247 rlineto
-10 vlineto
-304 -252 45 -57 206 173 rlineto
hintmask 11100000
923 hlineto
1 69 rlineto
-842 hlineto
endchar
</CharString>
<Subrs/>
<GlobalSubrs/>
</Glyph>
@@ -0,0 +1,7 @@
<Glyph name="hyphen.spacer" lsb="0" width="600">
<CharString>
endchar
</CharString>
<Subrs/>
<GlobalSubrs/>
</Glyph>
@@ -0,0 +1,14 @@
<Glyph name="hyphen_greater.liga" lsb="-431" width="550">
<CharString>
258 69 hstem
-431 896 vstem
138 602 rmoveto
-47 -58 264 -217 rlineto
-786 -69 787 hlineto
-269 -223 45 -57 333 280 rlineto
69 vlineto
endchar
</CharString>
<Subrs/>
<GlobalSubrs/>
</Glyph>
@@ -0,0 +1,15 @@
<Glyph name="hyphen_hyphen.liga" lsb="-341" width="550">
<CharString>
258 69 hstem
-341 317 63 317 vstem
-30 258 rmoveto
6 69 rlineto
-317 -69 hlineto
691 hmoveto
6 69 rlineto
-317 -69 hlineto
endchar
</CharString>
<Subrs/>
<GlobalSubrs/>
</Glyph>
@@ -0,0 +1,14 @@
<Glyph name="hyphen_hyphen_greater.liga" lsb="-981" width="550">
<CharString>
258 69 hstem
-981 1446 vstem
138 602 rmoveto
-47 -58 264 -217 rlineto
-1336 -69 1337 hlineto
-269 -223 45 -57 333 280 rlineto
69 vlineto
endchar
</CharString>
<Subrs/>
<GlobalSubrs/>
</Glyph>
@@ -0,0 +1,7 @@
<Glyph name="less.spacer" lsb="0" width="600">
<CharString>
endchar
</CharString>
<Subrs/>
<GlobalSubrs/>
</Glyph>
@@ -0,0 +1,17 @@
<Glyph name="less_bar.liga" lsb="-354" width="550">
<CharString>
-354 75 450 75 vstem
169 704 rmoveto
-523 -378 rlineto
-69 vlineto
523 -439 rlineto
75 892 hlineto
-523 -423 rmoveto
10 vlineto
448 317 rlineto
-700 vlineto
endchar
</CharString>
<Subrs/>
<GlobalSubrs/>
</Glyph>
@@ -0,0 +1,17 @@
<Glyph name="less_equal.2.liga" lsb="-283" width="600">
<CharString>
493 -141 69 hstem
-283 99 vstem
332 95 rmoveto
-516 252 rlineto
10 vlineto
512 247 -37 63 -574 -280 rlineto
-69 vlineto
615 -302 rlineto
-615 -157 rmoveto
615 69 -615 hlineto
endchar
</CharString>
<Subrs/>
<GlobalSubrs/>
</Glyph>
@@ -0,0 +1,17 @@
<Glyph name="less_equal.liga" lsb="-303" width="550">
<CharString>
138 77 103 69 hstem
-303 615 vstem
312 95 rmoveto
-516 252 rlineto
10 vlineto
512 247 -37 63 -574 -280 rlineto
-69 vlineto
584 -287 rlineto
-584 107 rmoveto
584 -287 31 64 -615 300 rlineto
endchar
</CharString>
<Subrs/>
<GlobalSubrs/>
</Glyph>
@@ -0,0 +1,22 @@
<Glyph name="less_equal_equal.liga" lsb="-1014" width="550">
<CharString>
151 69 153 69 hstemhm
-1014 75 -75 1486 hintmask 11100000
-939 287 rmoveto
10 vlineto
92 76 rlineto
hintmask 11010000
1318 hlineto
1 69 rlineto
-1236 hlineto
124 103 -45 58 -329 -277 rlineto
-69 vlineto
332 -279 46 57 -139 116 rlineto
1246 hlineto
1 69 rlineto
-1330 hlineto
endchar
</CharString>
<Subrs/>
<GlobalSubrs/>
</Glyph>
@@ -0,0 +1,29 @@
<Glyph name="less_equal_greater.liga" lsb="-1014" width="550">
<CharString>
151 69 153 69 hstemhm
-1014 75 -75 1479 -74 74 hintmask 11010000
138 602 rmoveto
-47 -58 124 -102 rlineto
-979 hlineto
124 103 -45 58 -329 -277 rlineto
-69 vlineto
332 -279 46 57 -139 116 rlineto
1002 hlineto
-140 -116 45 -57 333 280 rlineto
69 vlineto
hintmask 11001000
-74 -40 rmoveto
-81 -67 rlineto
-1168 hlineto
hintmask 11100000
-81 67 rlineto
10 vlineto
92 76 rlineto
1146 hlineto
hintmask 11001000
92 -76 rlineto
endchar
</CharString>
<Subrs/>
<GlobalSubrs/>
</Glyph>
@@ -0,0 +1,29 @@
<Glyph name="less_equal_less.liga" lsb="-1014" width="550">
<CharString>
151 69 153 69 hstemhm
-1014 75 -75 1478 -378 75 hintmask 11101000
418 -22 rmoveto
hintmask 11010000
46 57 -222 185 rlineto
hintmask 11101000
-81 67 rlineto
10 vlineto
299 248 -45 58 -191 -161 rlineto
-988 hlineto
124 103 -45 58 -329 -277 rlineto
-69 vlineto
332 -279 46 57 -139 116 rlineto
987 hlineto
-1070 69 rmoveto
-81 67 rlineto
10 vlineto
92 76 rlineto
989 hlineto
-56 -47 rlineto
-69 vlineto
44 -37 rlineto
endchar
</CharString>
<Subrs/>
<GlobalSubrs/>
</Glyph>
@@ -0,0 +1,29 @@
<Glyph name="less_exclam_hyphen_hyphen.liga" lsb="-1564" width="550">
<CharString>
0 110 148 69 hstemhm
-884 114 -78 84 hintmask 11010000
-848 234 rmoveto
53 hlineto
2 87 25 264 4 91 rrcurveto
-103 hlineto
2 -91 17 -264 -87 vvcurveto
-342 311 rmoveto
-45 58 -329 -277 rlineto
-69 vlineto
332 -279 46 57 -268 223 rlineto
384 hlineto
6 69 rlineto
-389 hlineto
872 hmoveto
-69 1011 vlineto
6 69 rlineto
hintmask 11100000
-1321 -327 rmoveto
113 hlineto
3 110 rlineto
-114 hlineto
endchar
</CharString>
<Subrs/>
<GlobalSubrs/>
</Glyph>
@@ -0,0 +1,15 @@
<Glyph name="less_hyphen.liga" lsb="-464" width="550">
<CharString>
258 69 hstem
-464 900 vstem
436 327 rmoveto
-789 hlineto
263 218 -45 58 -329 -277 rlineto
-69 vlineto
332 -279 46 57 -268 223 rlineto
784 hlineto
endchar
</CharString>
<Subrs/>
<GlobalSubrs/>
</Glyph>
@@ -0,0 +1,18 @@
<Glyph name="less_hyphen_greater.liga" lsb="-1014" width="550">
<CharString>
258 69 hstem
-1014 1479 vstem
138 602 rmoveto
-47 -58 264 -217 rlineto
-1258 hlineto
263 218 -45 58 -329 -277 rlineto
-69 vlineto
332 -279 46 57 -268 223 rlineto
1260 hlineto
-269 -223 45 -57 333 280 rlineto
69 vlineto
endchar
</CharString>
<Subrs/>
<GlobalSubrs/>
</Glyph>
@@ -0,0 +1,15 @@
<Glyph name="less_hyphen_hyphen.liga" lsb="-1014" width="550">
<CharString>
258 69 hstem
-1014 1450 vstem
436 327 rmoveto
-1339 hlineto
263 218 -45 58 -329 -277 rlineto
-69 vlineto
332 -279 46 57 -268 223 rlineto
1334 hlineto
endchar
</CharString>
<Subrs/>
<GlobalSubrs/>
</Glyph>
@@ -0,0 +1,15 @@
<Glyph name="less_slash.liga" lsb="-464" width="550">
<CharString>
-189 915 hstem
-464 75 182 534 vstem
258 726 rmoveto
-357 -680 -290 241 rlineto
10 vlineto
299 248 -45 58 -329 -277 rlineto
-69 vlineto
330 -277 -73 -140 71 -29 463 883 rlineto
endchar
</CharString>
<Subrs/>
<GlobalSubrs/>
</Glyph>
@@ -0,0 +1,7 @@
<Glyph name="plus.spacer" lsb="0" width="600">
<CharString>
endchar
</CharString>
<Subrs/>
<GlobalSubrs/>
</Glyph>
@@ -0,0 +1,12 @@
<Glyph name="plus_plus.liga" lsb="-428" width="550">
<CharString>
259 68 hstem
-250 73 352 73 vstem
248 327 rmoveto
187 -73 -187 -352 187 -73 -187 -178 -68 178 -187 73 187 352 -187 73 187 176 vlineto
1 68 rlineto
endchar
</CharString>
<Subrs/>
<GlobalSubrs/>
</Glyph>
@@ -0,0 +1,7 @@
<Glyph name="question.spacer" lsb="0" width="600">
<CharString>
endchar
</CharString>
<Subrs/>
<GlobalSubrs/>
</Glyph>
@@ -0,0 +1,31 @@
<Glyph name="question_question.liga" lsb="-395" width="550">
<CharString>
0 109 493 76 hstem
-304 111 110 86 73 111 110 86 vstem
-387 678 rmoveto
-8 -76 rlineto
252 -16 60 -40 -47 vvcurveto
-72 -180 -55 -8 -143 vhcurveto
57 -1 rlineto
14 129 203 51 110 vvcurveto
79 -88 65 -302 16 vhcurveto
380 hmoveto
-8 -76 rlineto
252 -16 60 -40 -47 vvcurveto
-72 -180 -55 -8 -143 vhcurveto
57 -1 rlineto
14 129 203 51 110 vvcurveto
79 -88 65 -302 16 vhcurveto
-298 -678 rmoveto
110 hlineto
3 109 rlineto
-111 hlineto
378 -109 rmoveto
110 hlineto
3 109 rlineto
-111 hlineto
endchar
</CharString>
<Subrs/>
<GlobalSubrs/>
</Glyph>
@@ -0,0 +1,7 @@
<Glyph name="slash.spacer" lsb="0" width="600">
<CharString>
endchar
</CharString>
<Subrs/>
<GlobalSubrs/>
</Glyph>
@@ -0,0 +1,14 @@
<Glyph name="slash_greater.liga" lsb="-347" width="550">
<CharString>
-189 915 hstem
-347 534 204 74 vstem
139 602 rmoveto
48 92 -69 32 -465 -886 71 -29 379 723 288 -237 rlineto
-10 vlineto
-304 -252 45 -57 333 280 rlineto
69 vlineto
endchar
</CharString>
<Subrs/>
<GlobalSubrs/>
</Glyph>
@@ -0,0 +1,7 @@
<Glyph name="underscore.spacer" lsb="0" width="600">
<CharString>
endchar
</CharString>
<Subrs/>
<GlobalSubrs/>
</Glyph>
@@ -0,0 +1,11 @@
<Glyph name="underscore_underscore.liga" lsb="-560" width="550">
<CharString>
-116 66 hstem
-560 1120 vstem
560 -50 rmoveto
-1120 -66 1120 hlineto
endchar
</CharString>
<Subrs/>
<GlobalSubrs/>
</Glyph>
@@ -0,0 +1,38 @@
<Glyph name="uniE0A0" code="0xe0a0" lsb="6" width="550">
<CharString>
-59 53 160 104 264 54 53 53 hstemhm
6 53 0 105 0 53 106 53 0 105 0 53 hintmask 1111010101000000
428 576 rmoveto
-58 -47 -47 -60 hvcurveto
hintmask 1111010010000000
-38 22 -34 31 -18 vhcurveto
-15 vlineto
-53 -53 -53 -53 -44 -34 -9 -15 -28 vhcurveto
251 vlineto
hintmask 1111101101000000
31 17 22 34 40 vvcurveto
58 -47 48 -58 -60 -46 -48 -58 vhcurveto
hintmask 1111010101000000
-40 21 -34 32 -17 vhcurveto
-347 vlineto
hintmask 1111101010000000
-32 -17 -21 -34 -40 vvcurveto
-58 46 -48 60 58 47 48 58 29 -11 25 -17 19 vhcurveto
18 16 24 16 41 hhcurveto
106 105 105 106 hvcurveto
14 vlineto
hintmask 1111010101000000
32 19 21 34 38 vvcurveto
59 -46 47 -60 vhcurveto
hintmask 1111101101000000
-316 53 rmoveto
28 24 -24 -29 -30 -24 -24 -28 -30 -23 24 30 29 23 24 30 hvcurveto
316 -212 rmoveto
-28 -24 24 28 30 24 23 28 30 23 -23 -30 -28 -23 -24 -30 hvcurveto
-316 -423 rmoveto
-30 -23 23 30 29 23 24 30 28 24 -24 -29 -30 -24 -23 -28 hvcurveto
endchar
</CharString>
<Subrs/>
<GlobalSubrs/>
</Glyph>
@@ -0,0 +1,11 @@
<Glyph name="uniE0B0" code="0xe0b0" lsb="-20" width="550">
<CharString>
-205 1099 hstem
-20 629 vstem
609 313 rmoveto
-627 581 -2 -1099 rlineto
endchar
</CharString>
<Subrs/>
<GlobalSubrs/>
</Glyph>
@@ -0,0 +1,11 @@
<Glyph name="uniE0B2" code="0xe0b2" lsb="-20" width="550">
<CharString>
-205 1099 hstem
-20 629 vstem
-20 313 rmoveto
629 -518 -2 1099 rlineto
endchar
</CharString>
<Subrs/>
<GlobalSubrs/>
</Glyph>
-164
View File
@@ -1,164 +0,0 @@
<GPOS>
<Version value="0x00010000"/>
<ScriptList>
<!-- ScriptCount=2 -->
<ScriptRecord index="0">
<ScriptTag value="DFLT"/>
<Script>
<DefaultLangSys>
<ReqFeatureIndex value="65535"/>
<!-- FeatureCount=1 -->
<FeatureIndex index="0" value="0"/>
</DefaultLangSys>
<!-- LangSysCount=0 -->
</Script>
</ScriptRecord>
<ScriptRecord index="1">
<ScriptTag value="latn"/>
<Script>
<DefaultLangSys>
<ReqFeatureIndex value="65535"/>
<!-- FeatureCount=1 -->
<FeatureIndex index="0" value="1"/>
</DefaultLangSys>
<!-- LangSysCount=3 -->
<LangSysRecord index="0">
<LangSysTag value="CAT "/>
<LangSys>
<ReqFeatureIndex value="65535"/>
<!-- FeatureCount=1 -->
<FeatureIndex index="0" value="2"/>
</LangSys>
</LangSysRecord>
<LangSysRecord index="1">
<LangSysTag value="MOL "/>
<LangSys>
<ReqFeatureIndex value="65535"/>
<!-- FeatureCount=1 -->
<FeatureIndex index="0" value="3"/>
</LangSys>
</LangSysRecord>
<LangSysRecord index="2">
<LangSysTag value="ROM "/>
<LangSys>
<ReqFeatureIndex value="65535"/>
<!-- FeatureCount=1 -->
<FeatureIndex index="0" value="4"/>
</LangSys>
</LangSysRecord>
</Script>
</ScriptRecord>
</ScriptList>
<FeatureList>
<!-- FeatureCount=5 -->
<FeatureRecord index="0">
<FeatureTag value="kern"/>
<Feature>
<!-- LookupCount=1 -->
<LookupListIndex index="0" value="0"/>
</Feature>
</FeatureRecord>
<FeatureRecord index="1">
<FeatureTag value="kern"/>
<Feature>
<!-- LookupCount=1 -->
<LookupListIndex index="0" value="0"/>
</Feature>
</FeatureRecord>
<FeatureRecord index="2">
<FeatureTag value="kern"/>
<Feature>
<!-- LookupCount=1 -->
<LookupListIndex index="0" value="0"/>
</Feature>
</FeatureRecord>
<FeatureRecord index="3">
<FeatureTag value="kern"/>
<Feature>
<!-- LookupCount=1 -->
<LookupListIndex index="0" value="0"/>
</Feature>
</FeatureRecord>
<FeatureRecord index="4">
<FeatureTag value="kern"/>
<Feature>
<!-- LookupCount=1 -->
<LookupListIndex index="0" value="0"/>
</Feature>
</FeatureRecord>
</FeatureList>
<LookupList>
<!-- LookupCount=1 -->
<Lookup index="0">
<LookupType value="2"/>
<LookupFlag value="0"/>
<!-- SubTableCount=1 -->
<PairPos index="0" Format="2">
<Coverage Format="2">
<Glyph value="zero.num"/>
<Glyph value="one.num"/>
<Glyph value="two.num"/>
<Glyph value="three.num"/>
<Glyph value="four.num"/>
<Glyph value="five.num"/>
<Glyph value="six.num"/>
<Glyph value="seven.num"/>
<Glyph value="eight.num"/>
<Glyph value="nine.num"/>
<Glyph value="fraction.afrc"/>
</Coverage>
<ValueFormat1 value="4"/>
<ValueFormat2 value="0"/>
<ClassDef1 Format="2">
<ClassDef glyph="eight.num" class="1"/>
<ClassDef glyph="five.num" class="1"/>
<ClassDef glyph="four.num" class="1"/>
<ClassDef glyph="nine.num" class="1"/>
<ClassDef glyph="one.num" class="1"/>
<ClassDef glyph="seven.num" class="1"/>
<ClassDef glyph="six.num" class="1"/>
<ClassDef glyph="three.num" class="1"/>
<ClassDef glyph="two.num" class="1"/>
<ClassDef glyph="zero.num" class="1"/>
</ClassDef1>
<ClassDef2 Format="2">
<ClassDef glyph="eight.den" class="1"/>
<ClassDef glyph="five.den" class="1"/>
<ClassDef glyph="four.den" class="1"/>
<ClassDef glyph="fraction.afrc" class="2"/>
<ClassDef glyph="nine.den" class="1"/>
<ClassDef glyph="one.den" class="1"/>
<ClassDef glyph="seven.den" class="1"/>
<ClassDef glyph="six.den" class="1"/>
<ClassDef glyph="three.den" class="1"/>
<ClassDef glyph="two.den" class="1"/>
<ClassDef glyph="zero.den" class="1"/>
</ClassDef2>
<!-- Class1Count=2 -->
<!-- Class2Count=3 -->
<Class1Record index="0">
<Class2Record index="0">
<Value1 XAdvance="0"/>
</Class2Record>
<Class2Record index="1">
<Value1 XAdvance="-550"/>
</Class2Record>
<Class2Record index="2">
<Value1 XAdvance="0"/>
</Class2Record>
</Class1Record>
<Class1Record index="1">
<Class2Record index="0">
<Value1 XAdvance="0"/>
</Class2Record>
<Class2Record index="1">
<Value1 XAdvance="0"/>
</Class2Record>
<Class2Record index="2">
<Value1 XAdvance="-550"/>
</Class2Record>
</Class1Record>
</PairPos>
</Lookup>
</LookupList>
</GPOS>

Some files were not shown because too many files have changed in this diff Show More