Compare commits
126 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 3813319b42 | |||
| f2a61c74ad | |||
| 1fce61fe50 | |||
| 1028c96291 | |||
| 043c160546 | |||
| 445828c8bf | |||
| 66fd3f94a1 | |||
| 9bf5f6197c | |||
| bd48389313 | |||
| 30a6c098e7 | |||
| 42e64f84b8 | |||
| 124d893fe5 | |||
| e692fcfbf8 | |||
| 321486d19e | |||
| 6f3d00ae6d | |||
| 420eeefe59 | |||
| a5c360bf30 | |||
| 93d4d03ef5 | |||
| 59435e4ee8 | |||
| cad9759288 | |||
| d3940070ed | |||
| 320fb069f7 | |||
| d6c1df83ed | |||
| 0b29866a3e | |||
| 9a70d50924 | |||
| 68741971f1 | |||
| bfae141c75 | |||
| 844b55f7b2 | |||
| 0c226a60bc | |||
| 2dd2079309 | |||
| 6f14cd709a | |||
| 06b5464fd6 | |||
| dc2d35f1c5 | |||
| 0823ed98af | |||
| 7b6eb72e66 | |||
| 53e9951957 | |||
| 44fc9b5ead | |||
| a86034b38d | |||
| c1bb4a9197 | |||
| 77244583f0 | |||
| f26cecc4bf | |||
| 732a29a79f | |||
| 258531d577 | |||
| 4cf344a435 | |||
| 63002e7901 | |||
| 38eb637717 | |||
| 2dbdb2543c | |||
| 4b908ad07b | |||
| a6dc28a403 | |||
| 84a4863e1f | |||
| 6fe2acd518 | |||
| 25051cfb52 | |||
| f91b91b7df | |||
| 1ed5f8afe4 | |||
| e87797d070 | |||
| 4e50610989 | |||
| 009dac1619 | |||
| 43d7f44527 | |||
| 9abc800918 | |||
| 10027973d8 | |||
| a9b6b1305d | |||
| 85cdb5c0a4 | |||
| 22d1a4d16d | |||
| 59466b8dfa | |||
| 2ed7ab50b3 | |||
| 37caa3ddea | |||
| b70accff53 | |||
| da7425fbe9 | |||
| 2282dd3d5d | |||
| d7e18a4962 | |||
| d71b04356a | |||
| 651edc2b62 | |||
| 02818d15a9 | |||
| 5c9a5d51a8 | |||
| fc180099b8 | |||
| 1f5712ecae | |||
| 2cbf9d84cb | |||
| d1c8620f6d | |||
| 0f10f62920 | |||
| fd4b980b7c | |||
| 286e5f0820 | |||
| 6e66c37704 | |||
| ad3050a731 | |||
| da1abf02c6 | |||
| 3a03d21c90 | |||
| 05bc5eaa4e | |||
| 03114bf88d | |||
| 83f9a6d170 | |||
| f0a883ee62 | |||
| 6e3415763c | |||
| 2bdf134f70 | |||
| edbbc78b82 | |||
| 4edf9bc945 | |||
| 538de4ad67 | |||
| 3550ee0bb1 | |||
| 65b938fdc1 | |||
| c5112089cb | |||
| 22ebd8aab7 | |||
| fe530d1ea9 | |||
| 19727aecc5 | |||
| 7a3be9b579 | |||
| 371be6a082 | |||
| 86b1d66f15 | |||
| 5538ffe2b5 | |||
| 360402a197 | |||
| f7cafe55b3 | |||
| 9cef42b1fb | |||
| 8360f4ad81 | |||
| 73f188856f | |||
| d2c63ad1ca | |||
| 0a7eca61d4 | |||
| fc8827e17c | |||
| 150ed13829 | |||
| 502f445758 | |||
| d3c5604090 | |||
| 61cfbf075d | |||
| 28eb8b58e5 | |||
| 91c4421765 | |||
| 3ed59809de | |||
| 660c719779 | |||
| 610140f1de | |||
| b6f785bfc7 | |||
| bc46df5f1c | |||
| 5f13b9c918 | |||
| 9398884dc6 | |||
| 036e837e0c |
@@ -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
|
||||
}
|
||||
@@ -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'
|
||||
}
|
||||
};
|
||||
@@ -0,0 +1 @@
|
||||
root: ./docs
|
||||
@@ -0,0 +1,47 @@
|
||||
---
|
||||
name: New ligature
|
||||
about: Use this template for requesting new ligatures.
|
||||
title: "Create `[LIGATURE NAME]` ligature"
|
||||
labels: enhancement
|
||||
---
|
||||
|
||||
<!-- Please only request a single ligature per issue, unless you would like something which has both symmetrical pairs (e.g. {{ and }}) -->
|
||||
|
||||
## Request preferences
|
||||
|
||||
* Weight requested: _State which weight you would like, and whether it is for SSm or not._
|
||||
|
||||
|
||||
## Ligature description
|
||||
|
||||
_Please descirbe the ligature here as best you can. Feel free to use images/screenshots to help us get ideas of how to implement it._
|
||||
|
||||
---
|
||||
|
||||
### Ligature variations
|
||||
|
||||
Due to how development is handled, not all ligatures are created at the same time. However, we will get to them all eventually. If you would like to help us develop ligatures, please reach out to us via email at kiliman@gmail.com
|
||||
|
||||
#### Operator Mono
|
||||
|
||||
- [ ] XLight
|
||||
- [ ] XLight Italic
|
||||
- [ ] Light
|
||||
- [ ] Light Italic
|
||||
- [ ] Book
|
||||
- [ ] Book Italic
|
||||
- [ ] Medium
|
||||
- [ ] Medium Italic
|
||||
- [ ] Bold
|
||||
- [ ] Bold Italic
|
||||
|
||||
#### Operator Mono SSm
|
||||
|
||||
- [ ] SSm Light
|
||||
- [ ] SSm Light Italic
|
||||
- [ ] SSm Book
|
||||
- [ ] SSm Book Italic
|
||||
- [ ] SSm Medium
|
||||
- [ ] SSm Medium Italic
|
||||
- [ ] SSm Bold
|
||||
- [ ] SSm Bold Italic
|
||||
@@ -1,4 +1,5 @@
|
||||
build
|
||||
node_modules
|
||||
.vscode/launch.json
|
||||
.idea
|
||||
.vscode
|
||||
.DS_Store
|
||||
|
||||
@@ -1,12 +1,42 @@
|
||||
# Operator Mono Ligatures
|
||||
|
||||
[](#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/vote)
|
||||
[](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)**
|
||||
|
||||
[](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!
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
|
After Width: | Height: | Size: 81 KiB |
|
After Width: | Height: | Size: 81 KiB |
|
After Width: | Height: | Size: 22 KiB |
|
After Width: | Height: | Size: 273 KiB |
|
After Width: | Height: | Size: 321 KiB |
|
After Width: | Height: | Size: 27 KiB |
|
After Width: | Height: | Size: 329 KiB |
|
After Width: | Height: | Size: 378 KiB |
|
After Width: | Height: | Size: 157 KiB |
|
After Width: | Height: | Size: 203 KiB |
|
After Width: | Height: | Size: 86 KiB |
|
After Width: | Height: | Size: 22 KiB |
|
After Width: | Height: | Size: 218 KiB |
|
After Width: | Height: | Size: 175 KiB |
|
After Width: | Height: | Size: 175 KiB |
|
After Width: | Height: | Size: 33 KiB |
|
After Width: | Height: | Size: 33 KiB |
@@ -0,0 +1,4 @@
|
||||
# Introduction
|
||||
|
||||
Testing
|
||||
|
||||
@@ -0,0 +1,19 @@
|
||||
# Table of contents
|
||||
|
||||
* [Introduction](README.md)
|
||||
* [Installation instructions](installation-instructions.md)
|
||||
* [Changelog](changelog.md)
|
||||
|
||||
## Developing ligatures
|
||||
|
||||
* [Setting up your development environment](developing-ligatures/setting-up-your-development-environment.md)
|
||||
* [Designing your first ligature](developing-ligatures/designing-your-first-ligature.md)
|
||||
* [Committing your Glyphs file](developing-ligatures/committing-your-glyphs-file.md)
|
||||
* [Ensuring ligatures work at small sizes](developing-ligatures/ensuring-ligatures-work-at-small-sizes.md)
|
||||
|
||||
## Ligature Recipes
|
||||
|
||||
* [www](ligature-recipes/www.md)
|
||||
* [Double-braces](ligature-recipes/double-braces/README.md)
|
||||
* [Roman variant](ligature-recipes/double-braces/roman-variant.md)
|
||||
|
||||
@@ -0,0 +1,26 @@
|
||||
---
|
||||
description: See what has changed each release.
|
||||
---
|
||||
|
||||
# Changelog
|
||||
|
||||
###
|
||||
|
||||
## 15.0.0 - 2042-12-0
|
||||
|
||||
### Fixed
|
||||
|
||||
* Removed humans, they weren't doing fine with animals.
|
||||
|
||||
### Changed
|
||||
|
||||
* Animals are now super cute, all of them.
|
||||
|
||||
## 14.0.0 - 2042-10-06
|
||||
|
||||
### Added
|
||||
|
||||
* Introduced animals into the world, we believe they're going to be a neat addition.
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,21 @@
|
||||
# Committing your Glyphs file
|
||||
|
||||
The Glyphs file is very difficult to merge, so standard tools like `git rebase` don't work well. I have created some tools that will allow you to update your existing Glyphs file on top of the current.
|
||||
|
||||
{% hint style="warning" %}
|
||||
Make sure you have created a separate branch for your changes and you've committed all your changes to the branch.
|
||||
{% endhint %}
|
||||
|
||||
1. When you're ready to issue a PR for your changes, you need to run the `./tools/glyphysrebase.sh` tool.
|
||||
2. You can now create your PR, or continue making changes and running the rebase tool periodically to keep up-to-date with master.
|
||||
|
||||
## How the tool works
|
||||
|
||||
1. Checks out a clean copy of `master` in a temporary folder.
|
||||
2. Copies your current working copy to a backup folder.
|
||||
3. Copies the master copy into your working copy \(basically resetting everything back before your changes\).
|
||||
4. Runs the `./tools/copyallglyphs.sh` script to copy ligatures from your backup folder to the current master in your working copy.
|
||||
5. At this point, you now have a glyphs file that includes your custom ligatures on top of the current master.
|
||||
6. The "rebased" files are then committed.
|
||||
7. You can now issue a PR. This should easily merge into master.
|
||||
|
||||
@@ -0,0 +1,23 @@
|
||||
# Designing your first ligature
|
||||
|
||||
## Getting Super Powers
|
||||
|
||||
Becoming a super hero is a fairly straight forward process:
|
||||
|
||||
```
|
||||
$ give me super-powers
|
||||
```
|
||||
|
||||
{% hint style="info" %}
|
||||
Super-powers are granted randomly so please submit an issue if you're not happy with yours.
|
||||
{% endhint %}
|
||||
|
||||
Once you're strong enough, save the world:
|
||||
|
||||
```
|
||||
// Ain't no code for that yet, sorry
|
||||
echo 'You got to trust me on this, I saved the world'
|
||||
```
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,6 @@
|
||||
# Ensuring ligatures work at small sizes
|
||||
|
||||
After creating each ligature, you going to need to make sure it works at very small sizes. Ensure the brace works at very small sizes by looking at it when its very small, by dragging up from the bottom of the editor. This need to be done because as [ScreenSmart fonts are guaranteed to work at a minimum of 9px](https://www.typography.com/fonts/operator/how-to-use#setting_text_and_headlines):
|
||||
|
||||

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

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

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

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

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

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

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

|
||||
|
||||

|
||||
|
||||

|
||||
|
||||

|
||||
|
||||
@@ -0,0 +1,14 @@
|
||||
---
|
||||
description: How to create the Roman variant of the double-brace ligature
|
||||
---
|
||||
|
||||
# Roman variant
|
||||
|
||||
{% hint style="info" %}
|
||||
|
||||
{% endhint %}
|
||||
|
||||
1. Add the `braceleft` component twice, or `braceright` component twice.
|
||||
2. Create a guide \(Right-click -> Add Guide\)
|
||||
3. Set the settings on the guide as so:
|
||||
|
||||
@@ -0,0 +1,2 @@
|
||||
# www
|
||||
|
||||
@@ -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 => {
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
calt.fea
|
||||
@@ -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);
|
||||
@@ -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);
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
After Width: | Height: | Size: 81 KiB |
|
After Width: | Height: | Size: 175 KiB |
|
After Width: | Height: | Size: 33 KiB |
@@ -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>
|
||||
@@ -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>
|
||||
@@ -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>
|
||||