├── source
├── lib
│ ├── __init__.py
│ ├── MutatorScale
│ │ ├── lib
│ │ │ ├── __init__.py
│ │ │ ├── mutatorScale
│ │ │ │ ├── pens
│ │ │ │ │ ├── __init__.py
│ │ │ │ │ └── utilityPens.py
│ │ │ │ ├── objects
│ │ │ │ │ ├── __init__.py
│ │ │ │ │ ├── errorGlyph.py
│ │ │ │ │ └── fonts.py
│ │ │ │ ├── utilities
│ │ │ │ │ ├── __init__.py
│ │ │ │ │ ├── numbersUtils.py
│ │ │ │ │ └── fontUtils.py
│ │ │ │ └── __init__.py
│ │ │ ├── testFonts
│ │ │ │ ├── two-axes
│ │ │ │ │ ├── bold-high-contrast.ufo
│ │ │ │ │ │ ├── glyphs
│ │ │ │ │ │ │ ├── B_.glif
│ │ │ │ │ │ │ ├── Aacute_.glif
│ │ │ │ │ │ │ ├── contents.plist
│ │ │ │ │ │ │ ├── I_.glif
│ │ │ │ │ │ │ ├── A_.glif
│ │ │ │ │ │ │ ├── O_.glif
│ │ │ │ │ │ │ └── H_.glif
│ │ │ │ │ │ ├── metainfo.plist
│ │ │ │ │ │ ├── fontinfo.plist
│ │ │ │ │ │ └── lib.plist
│ │ │ │ │ ├── bold-low-contrast.ufo
│ │ │ │ │ │ ├── glyphs
│ │ │ │ │ │ │ ├── B_.glif
│ │ │ │ │ │ │ ├── Aacute_.glif
│ │ │ │ │ │ │ ├── contents.plist
│ │ │ │ │ │ │ ├── I_.glif
│ │ │ │ │ │ │ ├── A_.glif
│ │ │ │ │ │ │ ├── O_.glif
│ │ │ │ │ │ │ └── H_.glif
│ │ │ │ │ │ ├── metainfo.plist
│ │ │ │ │ │ ├── fontinfo.plist
│ │ │ │ │ │ └── lib.plist
│ │ │ │ │ ├── bold-italic-low-contrast.ufo
│ │ │ │ │ │ ├── glyphs
│ │ │ │ │ │ │ ├── B_.glif
│ │ │ │ │ │ │ ├── Aacute_.glif
│ │ │ │ │ │ │ ├── contents.plist
│ │ │ │ │ │ │ ├── I_.glif
│ │ │ │ │ │ │ ├── A_.glif
│ │ │ │ │ │ │ ├── O_.glif
│ │ │ │ │ │ │ └── H_.glif
│ │ │ │ │ │ ├── metainfo.plist
│ │ │ │ │ │ ├── fontinfo.plist
│ │ │ │ │ │ └── lib.plist
│ │ │ │ │ ├── regular-high-contrast.ufo
│ │ │ │ │ │ ├── glyphs
│ │ │ │ │ │ │ ├── B_.glif
│ │ │ │ │ │ │ ├── Aacute_.glif
│ │ │ │ │ │ │ ├── contents.plist
│ │ │ │ │ │ │ ├── I_.glif
│ │ │ │ │ │ │ ├── A_.glif
│ │ │ │ │ │ │ ├── O_.glif
│ │ │ │ │ │ │ └── H_.glif
│ │ │ │ │ │ ├── metainfo.plist
│ │ │ │ │ │ └── fontinfo.plist
│ │ │ │ │ ├── regular-low-contrast.ufo
│ │ │ │ │ │ ├── glyphs
│ │ │ │ │ │ │ ├── B_.glif
│ │ │ │ │ │ │ ├── Aacute_.glif
│ │ │ │ │ │ │ ├── contents.plist
│ │ │ │ │ │ │ ├── I_.glif
│ │ │ │ │ │ │ ├── A_.glif
│ │ │ │ │ │ │ ├── O_.glif
│ │ │ │ │ │ │ └── H_.glif
│ │ │ │ │ │ ├── metainfo.plist
│ │ │ │ │ │ └── fontinfo.plist
│ │ │ │ │ └── regular-italic-low-contrast.ufo
│ │ │ │ │ │ ├── glyphs
│ │ │ │ │ │ ├── B_.glif
│ │ │ │ │ │ ├── Aacute_.glif
│ │ │ │ │ │ ├── contents.plist
│ │ │ │ │ │ ├── I_.glif
│ │ │ │ │ │ ├── A_.glif
│ │ │ │ │ │ ├── O_.glif
│ │ │ │ │ │ └── H_.glif
│ │ │ │ │ │ ├── metainfo.plist
│ │ │ │ │ │ └── fontinfo.plist
│ │ │ │ └── isotropic-anisotropic
│ │ │ │ │ ├── bold-mid-contrast.ufo
│ │ │ │ │ ├── glyphs
│ │ │ │ │ │ ├── B_.glif
│ │ │ │ │ │ ├── Aacute_.glif
│ │ │ │ │ │ ├── contents.plist
│ │ │ │ │ │ ├── I_.glif
│ │ │ │ │ │ ├── A_.glif
│ │ │ │ │ │ ├── O_.glif
│ │ │ │ │ │ └── H_.glif
│ │ │ │ │ ├── metainfo.plist
│ │ │ │ │ ├── fontinfo.plist
│ │ │ │ │ └── lib.plist
│ │ │ │ │ └── regular-mid-contrast.ufo
│ │ │ │ │ ├── glyphs
│ │ │ │ │ ├── B_.glif
│ │ │ │ │ ├── Aacute_.glif
│ │ │ │ │ ├── contents.plist
│ │ │ │ │ ├── I_.glif
│ │ │ │ │ ├── A_.glif
│ │ │ │ │ ├── O_.glif
│ │ │ │ │ └── H_.glif
│ │ │ │ │ ├── metainfo.plist
│ │ │ │ │ ├── fontinfo.plist
│ │ │ │ │ └── lib.plist
│ │ │ ├── robofont-test.py
│ │ │ └── test-no-UI.py
│ │ ├── images
│ │ │ ├── mutatorScale-1.png
│ │ │ ├── mutatorScale-2.png
│ │ │ ├── mutatorScale-3.png
│ │ │ ├── mutatorScale-4.png
│ │ │ ├── mutatorScale-5.png
│ │ │ └── mutatorScale-6.png
│ │ ├── .gitignore
│ │ ├── setup.py
│ │ ├── LICENSE.txt
│ │ └── Readme.md
│ └── dynamicParameters
│ │ ├── lib
│ │ └── dynamicParameters
│ │ │ ├── __init__.py
│ │ │ ├── parameterTest-Robofont.py
│ │ │ ├── vanillaParameterObjects.py
│ │ │ └── baseParameter.py
│ │ ├── slider-parameters.png
│ │ ├── License.txt
│ │ └── README.md
└── html
│ ├── images
│ ├── scalefast-1.png
│ ├── scalefast-2.png
│ ├── scalefast-3.png
│ ├── scalefast-4.png
│ ├── scalefast-5.png
│ ├── scalefast-6.png
│ ├── scalefast-7.png
│ ├── scalefast-8.png
│ ├── scalefast-9.png
│ ├── example-scalefast-1.png
│ ├── example-scalefast-2.png
│ ├── example-scalefast-3.png
│ ├── example-scalefast-4.png
│ ├── example-scalefast-5.png
│ ├── example-scalefast-6.png
│ └── example-scalefast-7.png
│ └── index.md
├── .gitignore
├── README.md
├── .github
└── workflows
│ └── validate_build.yml
├── info.yaml
└── notes.md
/source/lib/__init__.py:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/source/lib/MutatorScale/lib/__init__.py:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | *.pyc
2 | .DS_Store
3 | */.DS_Store
4 |
--------------------------------------------------------------------------------
/source/lib/MutatorScale/lib/mutatorScale/pens/__init__.py:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/source/lib/MutatorScale/lib/mutatorScale/objects/__init__.py:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/source/lib/MutatorScale/lib/mutatorScale/utilities/__init__.py:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/source/lib/dynamicParameters/lib/dynamicParameters/__init__.py:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/source/lib/MutatorScale/lib/mutatorScale/__init__.py:
--------------------------------------------------------------------------------
1 | __version__ = "0.4"
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | ScaleFast
2 | =========
3 |
4 | Documentation is [here](source/html/index.md)
--------------------------------------------------------------------------------
/source/html/images/scalefast-1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/roboDocs/ScaleFast/HEAD/source/html/images/scalefast-1.png
--------------------------------------------------------------------------------
/source/html/images/scalefast-2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/roboDocs/ScaleFast/HEAD/source/html/images/scalefast-2.png
--------------------------------------------------------------------------------
/source/html/images/scalefast-3.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/roboDocs/ScaleFast/HEAD/source/html/images/scalefast-3.png
--------------------------------------------------------------------------------
/source/html/images/scalefast-4.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/roboDocs/ScaleFast/HEAD/source/html/images/scalefast-4.png
--------------------------------------------------------------------------------
/source/html/images/scalefast-5.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/roboDocs/ScaleFast/HEAD/source/html/images/scalefast-5.png
--------------------------------------------------------------------------------
/source/html/images/scalefast-6.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/roboDocs/ScaleFast/HEAD/source/html/images/scalefast-6.png
--------------------------------------------------------------------------------
/source/html/images/scalefast-7.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/roboDocs/ScaleFast/HEAD/source/html/images/scalefast-7.png
--------------------------------------------------------------------------------
/source/html/images/scalefast-8.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/roboDocs/ScaleFast/HEAD/source/html/images/scalefast-8.png
--------------------------------------------------------------------------------
/source/html/images/scalefast-9.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/roboDocs/ScaleFast/HEAD/source/html/images/scalefast-9.png
--------------------------------------------------------------------------------
/source/html/images/example-scalefast-1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/roboDocs/ScaleFast/HEAD/source/html/images/example-scalefast-1.png
--------------------------------------------------------------------------------
/source/html/images/example-scalefast-2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/roboDocs/ScaleFast/HEAD/source/html/images/example-scalefast-2.png
--------------------------------------------------------------------------------
/source/html/images/example-scalefast-3.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/roboDocs/ScaleFast/HEAD/source/html/images/example-scalefast-3.png
--------------------------------------------------------------------------------
/source/html/images/example-scalefast-4.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/roboDocs/ScaleFast/HEAD/source/html/images/example-scalefast-4.png
--------------------------------------------------------------------------------
/source/html/images/example-scalefast-5.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/roboDocs/ScaleFast/HEAD/source/html/images/example-scalefast-5.png
--------------------------------------------------------------------------------
/source/html/images/example-scalefast-6.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/roboDocs/ScaleFast/HEAD/source/html/images/example-scalefast-6.png
--------------------------------------------------------------------------------
/source/html/images/example-scalefast-7.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/roboDocs/ScaleFast/HEAD/source/html/images/example-scalefast-7.png
--------------------------------------------------------------------------------
/source/lib/MutatorScale/images/mutatorScale-1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/roboDocs/ScaleFast/HEAD/source/lib/MutatorScale/images/mutatorScale-1.png
--------------------------------------------------------------------------------
/source/lib/MutatorScale/images/mutatorScale-2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/roboDocs/ScaleFast/HEAD/source/lib/MutatorScale/images/mutatorScale-2.png
--------------------------------------------------------------------------------
/source/lib/MutatorScale/images/mutatorScale-3.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/roboDocs/ScaleFast/HEAD/source/lib/MutatorScale/images/mutatorScale-3.png
--------------------------------------------------------------------------------
/source/lib/MutatorScale/images/mutatorScale-4.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/roboDocs/ScaleFast/HEAD/source/lib/MutatorScale/images/mutatorScale-4.png
--------------------------------------------------------------------------------
/source/lib/MutatorScale/images/mutatorScale-5.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/roboDocs/ScaleFast/HEAD/source/lib/MutatorScale/images/mutatorScale-5.png
--------------------------------------------------------------------------------
/source/lib/MutatorScale/images/mutatorScale-6.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/roboDocs/ScaleFast/HEAD/source/lib/MutatorScale/images/mutatorScale-6.png
--------------------------------------------------------------------------------
/source/lib/dynamicParameters/slider-parameters.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/roboDocs/ScaleFast/HEAD/source/lib/dynamicParameters/slider-parameters.png
--------------------------------------------------------------------------------
/source/lib/MutatorScale/.gitignore:
--------------------------------------------------------------------------------
1 | .DS_Store
2 | *.idea
3 | *.pyc
4 | *.sublime-project
5 | *.sublime-workspace
6 | lib/scaleFast-0.6.py
7 | build/
8 | lib/tests/
--------------------------------------------------------------------------------
/source/lib/MutatorScale/lib/testFonts/two-axes/bold-high-contrast.ufo/glyphs/B_.glif:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
--------------------------------------------------------------------------------
/source/lib/MutatorScale/lib/testFonts/two-axes/bold-low-contrast.ufo/glyphs/B_.glif:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
--------------------------------------------------------------------------------
/source/lib/MutatorScale/lib/testFonts/two-axes/bold-italic-low-contrast.ufo/glyphs/B_.glif:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
--------------------------------------------------------------------------------
/source/lib/MutatorScale/lib/testFonts/two-axes/regular-high-contrast.ufo/glyphs/B_.glif:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
--------------------------------------------------------------------------------
/source/lib/MutatorScale/lib/testFonts/two-axes/regular-low-contrast.ufo/glyphs/B_.glif:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
--------------------------------------------------------------------------------
/source/lib/MutatorScale/lib/testFonts/two-axes/regular-italic-low-contrast.ufo/glyphs/B_.glif:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
--------------------------------------------------------------------------------
/source/lib/MutatorScale/lib/testFonts/isotropic-anisotropic/bold-mid-contrast.ufo/glyphs/B_.glif:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
--------------------------------------------------------------------------------
/source/lib/MutatorScale/lib/testFonts/isotropic-anisotropic/regular-mid-contrast.ufo/glyphs/B_.glif:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
--------------------------------------------------------------------------------
/source/lib/MutatorScale/lib/testFonts/two-axes/bold-high-contrast.ufo/glyphs/Aacute_.glif:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/source/lib/MutatorScale/lib/testFonts/two-axes/bold-low-contrast.ufo/glyphs/Aacute_.glif:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/source/lib/MutatorScale/lib/testFonts/two-axes/regular-high-contrast.ufo/glyphs/Aacute_.glif:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/source/lib/MutatorScale/lib/testFonts/two-axes/regular-low-contrast.ufo/glyphs/Aacute_.glif:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/source/lib/MutatorScale/lib/testFonts/two-axes/bold-italic-low-contrast.ufo/glyphs/Aacute_.glif:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/source/lib/MutatorScale/lib/testFonts/isotropic-anisotropic/bold-mid-contrast.ufo/glyphs/Aacute_.glif:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/source/lib/MutatorScale/lib/testFonts/two-axes/regular-italic-low-contrast.ufo/glyphs/Aacute_.glif:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/source/lib/MutatorScale/lib/testFonts/isotropic-anisotropic/regular-mid-contrast.ufo/glyphs/Aacute_.glif:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/.github/workflows/validate_build.yml:
--------------------------------------------------------------------------------
1 | name: Validate and Build the Extension
2 | on:
3 | push
4 |
5 | jobs:
6 | validate_and_build:
7 | runs-on: ubuntu-latest
8 | steps:
9 | - name: Validate and Build
10 | uses: typemytype/roboFont-Extension-action@v0.1.0
11 | with:
12 | autotagging: true
--------------------------------------------------------------------------------
/info.yaml:
--------------------------------------------------------------------------------
1 | name: ScaleFast
2 | developer: "Loïc Sander"
3 | developerURL: https://github.com/loicsander
4 | launchAtStartUp: false
5 | mainScript: ''
6 | version: '1.1'
7 | addToMenu:
8 | - path: scaleFast.py
9 | preferredName: ScaleFast
10 | shortKey: ''
11 | html: true
12 | requiresVersionMajor: '3'
13 | requiresVersionMinor: '2'
14 |
--------------------------------------------------------------------------------
/source/lib/MutatorScale/lib/testFonts/two-axes/bold-high-contrast.ufo/metainfo.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | creator
6 | org.robofab.ufoLib
7 | formatVersion
8 | 2
9 |
10 |
11 |
--------------------------------------------------------------------------------
/source/lib/MutatorScale/lib/testFonts/two-axes/bold-low-contrast.ufo/metainfo.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | creator
6 | org.robofab.ufoLib
7 | formatVersion
8 | 2
9 |
10 |
11 |
--------------------------------------------------------------------------------
/source/lib/MutatorScale/lib/testFonts/two-axes/bold-italic-low-contrast.ufo/metainfo.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | creator
6 | org.robofab.ufoLib
7 | formatVersion
8 | 2
9 |
10 |
11 |
--------------------------------------------------------------------------------
/source/lib/MutatorScale/lib/testFonts/two-axes/regular-high-contrast.ufo/metainfo.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | creator
6 | org.robofab.ufoLib
7 | formatVersion
8 | 2
9 |
10 |
11 |
--------------------------------------------------------------------------------
/source/lib/MutatorScale/lib/testFonts/two-axes/regular-low-contrast.ufo/metainfo.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | creator
6 | org.robofab.ufoLib
7 | formatVersion
8 | 2
9 |
10 |
11 |
--------------------------------------------------------------------------------
/source/lib/MutatorScale/lib/testFonts/two-axes/regular-italic-low-contrast.ufo/metainfo.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | creator
6 | org.robofab.ufoLib
7 | formatVersion
8 | 2
9 |
10 |
11 |
--------------------------------------------------------------------------------
/source/lib/MutatorScale/lib/testFonts/isotropic-anisotropic/bold-mid-contrast.ufo/metainfo.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | creator
6 | org.robofab.ufoLib
7 | formatVersion
8 | 2
9 |
10 |
11 |
--------------------------------------------------------------------------------
/source/lib/MutatorScale/lib/testFonts/isotropic-anisotropic/regular-mid-contrast.ufo/metainfo.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | creator
6 | org.robofab.ufoLib
7 | formatVersion
8 | 2
9 |
10 |
11 |
--------------------------------------------------------------------------------
/notes.md:
--------------------------------------------------------------------------------
1 | Developer Notes
2 | ===============
3 |
4 | The ScaleFast extension contains code from two external modules:
5 |
6 | - [dynamicParameters](http://github.com/roboDocs/dynamicParameters)
7 | - [mutatorScale](http://github.com/roboDocs/MutatorScale)
8 |
9 | These modules are included in ScaleFast using `git subtree`.
10 |
11 | See [Git Subtree Merge](http://johnatten.com/2013/03/16/git-subtree-merge-the-quick-version/) for reference.
12 |
--------------------------------------------------------------------------------
/source/lib/MutatorScale/lib/testFonts/two-axes/bold-low-contrast.ufo/glyphs/contents.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | A
6 | A_.glif
7 | Aacute
8 | Aacute_.glif
9 | B
10 | B_.glif
11 | H
12 | H_.glif
13 | I
14 | I_.glif
15 | O
16 | O_.glif
17 |
18 |
19 |
--------------------------------------------------------------------------------
/source/lib/MutatorScale/lib/testFonts/two-axes/bold-high-contrast.ufo/glyphs/contents.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | A
6 | A_.glif
7 | Aacute
8 | Aacute_.glif
9 | B
10 | B_.glif
11 | H
12 | H_.glif
13 | I
14 | I_.glif
15 | O
16 | O_.glif
17 |
18 |
19 |
--------------------------------------------------------------------------------
/source/lib/MutatorScale/lib/testFonts/two-axes/regular-high-contrast.ufo/glyphs/contents.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | A
6 | A_.glif
7 | Aacute
8 | Aacute_.glif
9 | B
10 | B_.glif
11 | H
12 | H_.glif
13 | I
14 | I_.glif
15 | O
16 | O_.glif
17 |
18 |
19 |
--------------------------------------------------------------------------------
/source/lib/MutatorScale/lib/testFonts/two-axes/regular-low-contrast.ufo/glyphs/contents.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | A
6 | A_.glif
7 | Aacute
8 | Aacute_.glif
9 | B
10 | B_.glif
11 | H
12 | H_.glif
13 | I
14 | I_.glif
15 | O
16 | O_.glif
17 |
18 |
19 |
--------------------------------------------------------------------------------
/source/lib/MutatorScale/lib/testFonts/two-axes/bold-italic-low-contrast.ufo/glyphs/contents.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | A
6 | A_.glif
7 | Aacute
8 | Aacute_.glif
9 | B
10 | B_.glif
11 | H
12 | H_.glif
13 | I
14 | I_.glif
15 | O
16 | O_.glif
17 |
18 |
19 |
--------------------------------------------------------------------------------
/source/lib/MutatorScale/lib/testFonts/two-axes/regular-italic-low-contrast.ufo/glyphs/contents.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | A
6 | A_.glif
7 | Aacute
8 | Aacute_.glif
9 | B
10 | B_.glif
11 | H
12 | H_.glif
13 | I
14 | I_.glif
15 | O
16 | O_.glif
17 |
18 |
19 |
--------------------------------------------------------------------------------
/source/lib/MutatorScale/lib/testFonts/isotropic-anisotropic/bold-mid-contrast.ufo/glyphs/contents.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | A
6 | A_.glif
7 | Aacute
8 | Aacute_.glif
9 | B
10 | B_.glif
11 | H
12 | H_.glif
13 | I
14 | I_.glif
15 | O
16 | O_.glif
17 |
18 |
19 |
--------------------------------------------------------------------------------
/source/lib/MutatorScale/lib/testFonts/isotropic-anisotropic/regular-mid-contrast.ufo/glyphs/contents.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | A
6 | A_.glif
7 | Aacute
8 | Aacute_.glif
9 | B
10 | B_.glif
11 | H
12 | H_.glif
13 | I
14 | I_.glif
15 | O
16 | O_.glif
17 |
18 |
19 |
--------------------------------------------------------------------------------
/source/lib/MutatorScale/lib/mutatorScale/utilities/numbersUtils.py:
--------------------------------------------------------------------------------
1 | #coding=utf-8
2 | from __future__ import division
3 |
4 | def mapValue(value, values1, values2):
5 | '''
6 | For a value provided with an initial set of reference values,
7 | returns a new one proportionally defined between a second set of values.
8 | '''
9 | lowValue1, highValue1 = values1
10 | lowValue2, highValue2 = values2
11 |
12 | delta1 = highValue1 - lowValue1
13 | delta2 = highValue2 - lowValue2
14 | if delta1 != 0:
15 | factor = (value - lowValue1) / delta1
16 | value = lowValue2 + (delta2 * factor)
17 | return value
--------------------------------------------------------------------------------
/source/lib/MutatorScale/lib/robofont-test.py:
--------------------------------------------------------------------------------
1 | from mutatorScale.objects.scaler import MutatorScaleEngine
2 |
3 | # To test this, open some interpolatable fonts (if you don’t have any (duh?), use those in the TestFonts folder)
4 |
5 | fonts = [font for font in AllFonts() if font.info.familyName != 'Output']
6 |
7 | scaler = MutatorScaleEngine(fonts)
8 | scaler.set({
9 | 'scale':(0.85, 0.8)
10 | })
11 |
12 | f = RFont(showInterface=False)
13 | f.info.familyName = 'Output'
14 |
15 | for glyphName in ['A','H','I','O']:
16 | stemValues = (100, 70)
17 | g = scaler.getScaledGlyph(glyphName, stemValues)
18 | f.insertGlyph(g, glyphName)
19 |
20 | f.openInterface()
21 |
22 |
--------------------------------------------------------------------------------
/source/lib/MutatorScale/setup.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 |
3 | from distutils.core import setup
4 |
5 | setup(name = "MutatorScale",
6 | version = "0.6",
7 | description = "Tool for interpolated glyph scaling, based on Robofab, FontTools & MutatorMath.",
8 | author = "Loic Sander",
9 | author_email = "loic@akalollip.com",
10 | url = "https://github.com/loicsander/MutatorScale",
11 | license = "MIT",
12 | packages = [
13 | "mutatorScale",
14 | "mutatorScale.booleanOperations",
15 | "mutatorScale.objects",
16 | "mutatorScale.pens",
17 | "mutatorScale.utilities",
18 | ],
19 | package_dir = {"":"lib"},
20 | )
21 |
--------------------------------------------------------------------------------
/source/lib/MutatorScale/lib/test-no-UI.py:
--------------------------------------------------------------------------------
1 | #coding=utf-8
2 |
3 | from mutatorScale.objects.scaler import MutatorScaleEngine
4 | from mutatorScale.utilities.fontUtils import intersect
5 |
6 | from fontParts.fontshell import RFont
7 |
8 | paths = [
9 | 'testFonts/two-axes/regular-low-contrast.ufo',
10 | 'testFonts/two-axes/bold-low-contrast.ufo'
11 | ]
12 | outputPath = 'testFonts/two-axes/scaled-low-contrast.ufo'
13 |
14 | fonts = []
15 | for p in paths:
16 | fonts.append(RFont(p))
17 |
18 | scaler = MutatorScaleEngine(fonts)
19 | scaler.set({
20 | 'scale' : (0.85, 0.8)
21 | })
22 |
23 | outputFont = RFont()
24 | for glyphName in 'AHIO':
25 | glyph = scaler.getScaledGlyph(glyphName, (95, 75))
26 | outputFont.insertGlyph(glyph, glyphName)
27 |
28 | outputFont.save(outputPath)
--------------------------------------------------------------------------------
/source/lib/MutatorScale/lib/testFonts/two-axes/bold-high-contrast.ufo/glyphs/I_.glif:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
--------------------------------------------------------------------------------
/source/lib/MutatorScale/lib/testFonts/two-axes/bold-low-contrast.ufo/glyphs/I_.glif:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
--------------------------------------------------------------------------------
/source/lib/MutatorScale/lib/testFonts/two-axes/regular-high-contrast.ufo/glyphs/I_.glif:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
--------------------------------------------------------------------------------
/source/lib/MutatorScale/lib/testFonts/two-axes/regular-low-contrast.ufo/glyphs/I_.glif:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
--------------------------------------------------------------------------------
/source/lib/MutatorScale/lib/testFonts/isotropic-anisotropic/bold-mid-contrast.ufo/glyphs/I_.glif:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
--------------------------------------------------------------------------------
/source/lib/MutatorScale/lib/testFonts/isotropic-anisotropic/regular-mid-contrast.ufo/glyphs/I_.glif:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
--------------------------------------------------------------------------------
/source/lib/MutatorScale/lib/testFonts/two-axes/bold-italic-low-contrast.ufo/glyphs/I_.glif:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
--------------------------------------------------------------------------------
/source/lib/MutatorScale/lib/testFonts/two-axes/regular-italic-low-contrast.ufo/glyphs/I_.glif:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
--------------------------------------------------------------------------------
/source/lib/MutatorScale/lib/testFonts/two-axes/bold-low-contrast.ufo/fontinfo.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | ascender
6 | 750
7 | capHeight
8 | 750
9 | descender
10 | -250
11 | familyName
12 | Test Low Contrast
13 | postscriptBlueValues
14 |
15 |
16 | postscriptFamilyBlues
17 |
18 |
19 | postscriptFamilyOtherBlues
20 |
21 |
22 | postscriptOtherBlues
23 |
24 |
25 | postscriptStemSnapH
26 |
27 |
28 | postscriptStemSnapV
29 |
30 |
31 | styleName
32 | Bold
33 | unitsPerEm
34 | 1000
35 | xHeight
36 | 500
37 |
38 |
39 |
--------------------------------------------------------------------------------
/source/lib/MutatorScale/lib/testFonts/two-axes/bold-high-contrast.ufo/fontinfo.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | ascender
6 | 750
7 | capHeight
8 | 750
9 | descender
10 | -250
11 | familyName
12 | Test High Contrast
13 | postscriptBlueValues
14 |
15 |
16 | postscriptFamilyBlues
17 |
18 |
19 | postscriptFamilyOtherBlues
20 |
21 |
22 | postscriptOtherBlues
23 |
24 |
25 | postscriptStemSnapH
26 |
27 |
28 | postscriptStemSnapV
29 |
30 |
31 | styleName
32 | Bold
33 | unitsPerEm
34 | 1000
35 | xHeight
36 | 500
37 |
38 |
39 |
--------------------------------------------------------------------------------
/source/lib/MutatorScale/lib/testFonts/two-axes/regular-low-contrast.ufo/fontinfo.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | ascender
6 | 750
7 | capHeight
8 | 750
9 | descender
10 | -250
11 | familyName
12 | Test Low Contrast
13 | postscriptBlueValues
14 |
15 |
16 | postscriptFamilyBlues
17 |
18 |
19 | postscriptFamilyOtherBlues
20 |
21 |
22 | postscriptOtherBlues
23 |
24 |
25 | postscriptStemSnapH
26 |
27 |
28 | postscriptStemSnapV
29 |
30 |
31 | styleName
32 | Regular
33 | unitsPerEm
34 | 1000
35 | xHeight
36 | 500
37 |
38 |
39 |
--------------------------------------------------------------------------------
/source/lib/MutatorScale/lib/testFonts/two-axes/regular-high-contrast.ufo/fontinfo.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | ascender
6 | 750
7 | capHeight
8 | 750
9 | descender
10 | -250
11 | familyName
12 | Test High Contrast
13 | postscriptBlueValues
14 |
15 |
16 | postscriptFamilyBlues
17 |
18 |
19 | postscriptFamilyOtherBlues
20 |
21 |
22 | postscriptOtherBlues
23 |
24 |
25 | postscriptStemSnapH
26 |
27 |
28 | postscriptStemSnapV
29 |
30 |
31 | styleName
32 | Regular
33 | unitsPerEm
34 | 1000
35 | xHeight
36 | 500
37 |
38 |
39 |
--------------------------------------------------------------------------------
/source/lib/MutatorScale/lib/testFonts/isotropic-anisotropic/bold-mid-contrast.ufo/fontinfo.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | ascender
6 | 750
7 | capHeight
8 | 750
9 | descender
10 | -250
11 | familyName
12 | Test Mid Contrast
13 | postscriptBlueValues
14 |
15 |
16 | postscriptFamilyBlues
17 |
18 |
19 | postscriptFamilyOtherBlues
20 |
21 |
22 | postscriptOtherBlues
23 |
24 |
25 | postscriptStemSnapH
26 |
27 |
28 | postscriptStemSnapV
29 |
30 |
31 | styleName
32 | Bold
33 | unitsPerEm
34 | 1000
35 | xHeight
36 | 500
37 |
38 |
39 |
--------------------------------------------------------------------------------
/source/lib/MutatorScale/lib/testFonts/two-axes/bold-italic-low-contrast.ufo/fontinfo.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | ascender
6 | 750
7 | capHeight
8 | 750
9 | descender
10 | -250
11 | familyName
12 | Test Low Contrast
13 | postscriptBlueValues
14 |
15 |
16 | postscriptFamilyBlues
17 |
18 |
19 | postscriptFamilyOtherBlues
20 |
21 |
22 | postscriptOtherBlues
23 |
24 |
25 | postscriptStemSnapH
26 |
27 |
28 | postscriptStemSnapV
29 |
30 |
31 | styleName
32 | Bold Italic
33 | unitsPerEm
34 | 1000
35 | xHeight
36 | 500
37 |
38 |
39 |
--------------------------------------------------------------------------------
/source/lib/MutatorScale/lib/testFonts/isotropic-anisotropic/regular-mid-contrast.ufo/fontinfo.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | ascender
6 | 750
7 | capHeight
8 | 750
9 | descender
10 | -250
11 | familyName
12 | Test Mid Contrast
13 | postscriptBlueValues
14 |
15 |
16 | postscriptFamilyBlues
17 |
18 |
19 | postscriptFamilyOtherBlues
20 |
21 |
22 | postscriptOtherBlues
23 |
24 |
25 | postscriptStemSnapH
26 |
27 |
28 | postscriptStemSnapV
29 |
30 |
31 | styleName
32 | Regular
33 | unitsPerEm
34 | 1000
35 | xHeight
36 | 500
37 |
38 |
39 |
--------------------------------------------------------------------------------
/source/lib/MutatorScale/lib/testFonts/two-axes/regular-italic-low-contrast.ufo/fontinfo.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | ascender
6 | 750
7 | capHeight
8 | 750
9 | descender
10 | -250
11 | familyName
12 | Test Low Contrast
13 | postscriptBlueValues
14 |
15 |
16 | postscriptFamilyBlues
17 |
18 |
19 | postscriptFamilyOtherBlues
20 |
21 |
22 | postscriptOtherBlues
23 |
24 |
25 | postscriptStemSnapH
26 |
27 |
28 | postscriptStemSnapV
29 |
30 |
31 | styleName
32 | Regular Italic
33 | unitsPerEm
34 | 1000
35 | xHeight
36 | 500
37 |
38 |
39 |
--------------------------------------------------------------------------------
/source/lib/MutatorScale/LICENSE.txt:
--------------------------------------------------------------------------------
1 | The MIT License (MIT)
2 |
3 | Copyright (c) 2015 Loïc Sander
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
--------------------------------------------------------------------------------
/source/lib/dynamicParameters/License.txt:
--------------------------------------------------------------------------------
1 | The MIT License (MIT)
2 |
3 | Copyright (c) 2014 Loïc Sander
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/source/lib/dynamicParameters/lib/dynamicParameters/parameterTest-Robofont.py:
--------------------------------------------------------------------------------
1 | import os
2 | import sys
3 |
4 | dynamicParametersLibFolder = os.path.dirname(os.getcwd())
5 | if not dynamicParametersLibFolder in sys.path:
6 | sys.path.insert(0, dynamicParametersLibFolder)
7 |
8 | from dynamicParameters.vanillaParameterObjects import ParameterSliderTextInput, VanillaSingleValueParameter
9 | from vanilla import Window, Group
10 |
11 | class ParameterTester:
12 |
13 | def __init__(self):
14 | self.w = Window((300, 100))
15 | self.w.inner = Group((10, 10, -10, -10))
16 |
17 | p1 = VanillaSingleValueParameter('main', 10, (0, 100), 'int')
18 | p2 = VanillaSingleValueParameter('ratio', 10, (0, 100), 'int', master=p1, mode='ratio', dissociable=True)
19 | p3 = VanillaSingleValueParameter('offset', 10, (0, 100), 'int', master=p1, mode='offset', dissociable=True)
20 |
21 | self.w.inner.p1 = ParameterSliderTextInput(p1, (0, 0, -0, 22), 'master')
22 | self.w.inner.p2 = ParameterSliderTextInput(p2, (0, 25, -0, 22), 'ratio')
23 | self.w.inner.p3 = ParameterSliderTextInput(p3, (0, 50, -0, 22), 'offset')
24 | self.w.open()
25 |
26 | ParameterTester()
27 |
--------------------------------------------------------------------------------
/source/lib/MutatorScale/lib/testFonts/two-axes/bold-low-contrast.ufo/glyphs/A_.glif:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
--------------------------------------------------------------------------------
/source/lib/MutatorScale/lib/testFonts/two-axes/regular-low-contrast.ufo/glyphs/A_.glif:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
--------------------------------------------------------------------------------
/source/lib/MutatorScale/lib/testFonts/isotropic-anisotropic/bold-mid-contrast.ufo/glyphs/A_.glif:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
--------------------------------------------------------------------------------
/source/lib/MutatorScale/lib/testFonts/isotropic-anisotropic/regular-mid-contrast.ufo/glyphs/A_.glif:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
--------------------------------------------------------------------------------
/source/lib/MutatorScale/lib/testFonts/two-axes/bold-high-contrast.ufo/glyphs/A_.glif:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
--------------------------------------------------------------------------------
/source/lib/MutatorScale/lib/testFonts/two-axes/regular-high-contrast.ufo/glyphs/A_.glif:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
--------------------------------------------------------------------------------
/source/lib/MutatorScale/lib/testFonts/two-axes/bold-low-contrast.ufo/glyphs/O_.glif:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
--------------------------------------------------------------------------------
/source/lib/MutatorScale/lib/testFonts/isotropic-anisotropic/bold-mid-contrast.ufo/glyphs/O_.glif:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
--------------------------------------------------------------------------------
/source/lib/MutatorScale/lib/testFonts/isotropic-anisotropic/regular-mid-contrast.ufo/glyphs/O_.glif:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
--------------------------------------------------------------------------------
/source/lib/MutatorScale/lib/testFonts/two-axes/bold-high-contrast.ufo/glyphs/O_.glif:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
--------------------------------------------------------------------------------
/source/lib/MutatorScale/lib/testFonts/two-axes/regular-low-contrast.ufo/glyphs/O_.glif:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
--------------------------------------------------------------------------------
/source/lib/MutatorScale/lib/testFonts/two-axes/regular-high-contrast.ufo/glyphs/O_.glif:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
--------------------------------------------------------------------------------
/source/lib/MutatorScale/lib/testFonts/two-axes/bold-italic-low-contrast.ufo/glyphs/A_.glif:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
--------------------------------------------------------------------------------
/source/lib/MutatorScale/lib/testFonts/two-axes/regular-italic-low-contrast.ufo/glyphs/A_.glif:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
--------------------------------------------------------------------------------
/source/lib/MutatorScale/lib/testFonts/two-axes/bold-high-contrast.ufo/glyphs/H_.glif:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
--------------------------------------------------------------------------------
/source/lib/MutatorScale/lib/testFonts/two-axes/regular-high-contrast.ufo/glyphs/H_.glif:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
--------------------------------------------------------------------------------
/source/lib/MutatorScale/lib/testFonts/two-axes/regular-low-contrast.ufo/glyphs/H_.glif:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
--------------------------------------------------------------------------------
/source/lib/MutatorScale/lib/testFonts/two-axes/bold-low-contrast.ufo/glyphs/H_.glif:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
--------------------------------------------------------------------------------
/source/lib/MutatorScale/lib/testFonts/two-axes/bold-italic-low-contrast.ufo/glyphs/O_.glif:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
--------------------------------------------------------------------------------
/source/lib/MutatorScale/lib/testFonts/two-axes/regular-italic-low-contrast.ufo/glyphs/O_.glif:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
--------------------------------------------------------------------------------
/source/lib/MutatorScale/lib/testFonts/isotropic-anisotropic/bold-mid-contrast.ufo/glyphs/H_.glif:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
--------------------------------------------------------------------------------
/source/lib/MutatorScale/lib/testFonts/isotropic-anisotropic/regular-mid-contrast.ufo/glyphs/H_.glif:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
--------------------------------------------------------------------------------
/source/lib/MutatorScale/lib/testFonts/two-axes/regular-italic-low-contrast.ufo/glyphs/H_.glif:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
--------------------------------------------------------------------------------
/source/lib/MutatorScale/lib/testFonts/two-axes/bold-italic-low-contrast.ufo/glyphs/H_.glif:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
--------------------------------------------------------------------------------
/source/lib/MutatorScale/lib/mutatorScale/pens/utilityPens.py:
--------------------------------------------------------------------------------
1 | #coding=utf-8
2 | from fontTools.pens.basePen import BasePen
3 |
4 | try: # RF >= 3.3b
5 | from fontTools.pens.pointPen import AbstractPointPen
6 | except:
7 | from ufoLib.pointPen import AbstractPointPen
8 |
9 |
10 | class ClockwiseTestPointPen(AbstractPointPen):
11 |
12 | def __init__(self):
13 | self._points = []
14 |
15 | def beginPath(self):
16 | pass
17 |
18 | def endPath(self):
19 | pass
20 |
21 | def addPoint(self, pt, segmentType=None, smooth=False, name=None, **kwargs):
22 | if segmentType:
23 | # overlapping points can give false results, so filter them out
24 | if self._points and self._points[-1] == pt:
25 | return
26 | self._points.append(pt)
27 |
28 | def getIsClockwise(self):
29 | points = self._points
30 | pointCount = len(points)
31 | # overlapping moves can give false results, so filter them out
32 | if points[0] == points[-1]:
33 | del points[-1]
34 | total = 0
35 |
36 | for index1 in xrange(pointCount):
37 | index2 = (index1 + 1) % pointCount
38 | x1, y1 = points[index1]
39 | x2, y2 = points[index2]
40 | total += (x1*y2)-(x2*y1)
41 |
42 | return total < 0
43 |
44 | class CollectSegmentsPen(BasePen):
45 |
46 | def __init__(self, glyphSet):
47 | self.glyphSet = glyphSet
48 | self.contours = []
49 |
50 | def _moveTo(self, pt):
51 | self.segments = []
52 | self.previousPoint = pt
53 |
54 | def _lineTo(self, pt):
55 | self.segments.append((self.previousPoint, pt))
56 | self.previousPoint = pt
57 |
58 | def _curveToOne(self, pt1, pt2, pt3):
59 | self.segments.append((self.previousPoint, pt1, pt2, pt3))
60 | self.previousPoint = pt3
61 |
62 | def endPath(self):
63 | self.contours.append(self.segments)
64 |
65 | def closePath(self):
66 | self.segments.append((self.previousPoint, self.segments[0][0]))
67 | self.contours.append(self.segments)
68 |
69 | def getSegments(self):
70 | return self.contours
--------------------------------------------------------------------------------
/source/lib/dynamicParameters/README.md:
--------------------------------------------------------------------------------
1 | Dynamic Parameters
2 | ==================
3 |
4 | ## SingleValueParameter
5 | *(baseParameter.py)*
6 |
7 | This is an almost simple & independent object built to help defining values in relation to others, on a master/slave basis.
8 | Each instance of the SingleValueParameter bears a value and is either a master or a slave (or both). There’s no ideology in the choice of words, you can also call them parent and children. The value of a parameter that is enslaved to another will change with its master’s value, based on a ratio, or an offset value.
9 | The whole point of this object was primarily to make it easier to have dynamically linked values in a basic UI, but it can be used without any UI.
10 |
11 | At the least, a parameter object requires a name and a default value.
12 |
13 | ```python
14 | p = SingleValueParameter('myParameter', 40)
15 | ```
16 |
17 | and here’s the whole object:
18 | ```python
19 | SingleValueParameter(name, defaultValue, limits=None, numType='float', master=None, mode=None)
20 | ```
21 |
22 | + *limits* should be a tuple in the form (minValue, maxValue)
23 | + *numType* can be either ‘int’ or ‘float’ (used to format the output)
24 | + *master* would be another parameter object
25 | + *mode* the type of relationship to the master parameter, ‘ratio’ or ‘offset’
26 |
27 | Defining a parameter’s value goes trough the **set()** method:
28 | ```python
29 | p.set(40)
30 | ```
31 |
32 | If the parameter happens to be the master of other parameters, all the slave parameters will be modified as well, based on their ratio/offset. A parameter given a master but no mode will fail.
33 |
34 | The relationship can be changed at any time **setMode()**, and a slave parameter can be freed at any time as well with **setMaster(None)**.
35 |
36 | Independently from the chosen mode, 'ratio' or 'offset', the ratio and offset values can be retrieved with **getRatio()** and **getOffset**. Inversely, and still independent of the mode, ratio and offset can be set, **setRatio()**, **setOffset()**.
37 |
38 | Similarly, values of a parameter can be set relatively through the **set()** method: adding ('++20') or substracting ('--20'). Note that these inputs have to be strings for the ++ and -- operators to be considered.
39 |
40 | ## VanillaSingleValueParameter
41 | *(vanillaParameterObjects.py)*
42 |
43 | This is the UI linked implementation of the SingleValueParameter object. Specifically, it is made to function with  based UI elements for use inside of Robofont or DrawBot (or any application using , I guess).
44 |
45 | 
46 |
47 | ## ParameterSliderTextInput
48 | *(vanillaParameterObjects.py)*
49 |
50 | And here’s a bunch of  object grouped together (a slider, text input and checkbox), linking the slider and text input values through the ways of a parameter object.
51 |
--------------------------------------------------------------------------------
/source/lib/MutatorScale/lib/mutatorScale/objects/errorGlyph.py:
--------------------------------------------------------------------------------
1 | #coding=utf8
2 | from __future__ import division
3 |
4 | from math import pi, cos, sin, hypot
5 |
6 | from fontParts.fontshell import RGlyph
7 |
8 | _LETTERFORMS = {
9 | 'interpolation':[
10 | (296, 322), (201, 322),
11 | (201, 352), (231, 352),
12 | (231, 397), (201, 397),
13 | (201, 427), (296, 427),
14 | (296, 397), (266, 397),
15 | (266, 352), (296, 352)
16 | ],
17 | 'none':[
18 | (231, 322), (201, 322),
19 | (201, 427), (236, 427),
20 | (266, 374), (266, 427),
21 | (296, 427), (296, 322),
22 | (261, 322), (231, 375)
23 | ]
24 | }
25 |
26 | class ErrorGlyph(RGlyph):
27 |
28 | def __new__(cls, errorName=None, report=None, size=500, upm=1000):
29 | newGlyph = super(ErrorGlyph, cls).__new__(cls)
30 | newGlyph.__init__(errorName, report, size, upm)
31 | return newGlyph
32 |
33 | def __init__(self, errorName=None, report=None, size=500, upm=1000):
34 | super(ErrorGlyph, self).__init__()
35 | self.note = str(report)
36 | self.name = '_error_'
37 | self.upm = upm
38 | self.pen = self.getPen()
39 | size = 300
40 | self._setSize(size)
41 | self.width = 500
42 | self._drawError(errorName)
43 | scale = upm / 1000
44 | self.scaleBy((scale, scale))
45 |
46 | def _setSize(self, size):
47 | self.si = size
48 | self.st = (
49 | 250 - (size / 4),
50 | (750 / 2) - (size / 2)
51 | )
52 | self.le = hypot(size, size) / 4
53 |
54 | def _drawError(self, errorName):
55 | errorSign = self._getErrorSign()
56 | self._drawPoints(errorSign)
57 | if errorName is not None:
58 | points = self._getLetter(errorName)
59 | self._drawPoints(points)
60 |
61 | def _drawPoints(self, points):
62 | pen = self.pen
63 | for i, point in enumerate(points):
64 | if i == 0:
65 | pen.moveTo(point)
66 | else:
67 | pen.lineTo(point)
68 | pen.closePath()
69 |
70 | def _getErrorSign(self):
71 | points = []
72 | a = pi/4
73 | size = self.le
74 | start = self.st
75 | px, py = start
76 | for i in range(12):
77 | x = px + (size * cos(a))
78 | y = py + (size * sin(a))
79 | points.append((x, y))
80 | px = x
81 | py = y
82 | if i%3 == 0:
83 | a -= pi/2
84 | elif i%3 != 0:
85 | a += pi/2
86 | return points
87 |
88 | def _getLetter(self, errorName):
89 | errorName = errorName.lower()
90 | if errorName in _LETTERFORMS:
91 | return _LETTERFORMS[errorName]
92 |
93 | if __name__ == '__main__':
94 |
95 | import unittest
96 |
97 | class ErrorGlyphTests(unittest.TestCase):
98 |
99 | def test_building_errorGlyph_with_note(self):
100 | for letter in _LETTERFORMS:
101 | e = ErrorGlyph(letter, report='No idea what happened.')
102 |
103 | def test_building_errorGlyphs(self):
104 | for letter in _LETTERFORMS:
105 | e = ErrorGlyph(letter)
106 |
107 | unittest.main()
108 |
--------------------------------------------------------------------------------
/source/lib/dynamicParameters/lib/dynamicParameters/vanillaParameterObjects.py:
--------------------------------------------------------------------------------
1 | # coding=utf-8
2 | # Loïc Sander — 2014
3 | from .baseParameter import SingleValueParameter
4 | from vanilla import Group, Slider, TextBox, CheckBox
5 | from mojo.UI import NumberEditText
6 |
7 | class BaseParameterVanillaInput:
8 |
9 | vanillaInputs = []
10 |
11 | def __init__(self, parameter, posSize, callback=None):
12 | self.parameter = parameter
13 | self.callback = callback
14 |
15 | def get(self):
16 | return self.parameter.get()
17 |
18 | def enable(self, value):
19 | for item in self.vanillaInputs:
20 | item.enable(value)
21 |
22 | def valueInput(self, sender):
23 | value = sender.get()
24 | parameter = self.parameter
25 | if value == 'R':
26 | parameter.reset()
27 | parameter.update()
28 | if self.callback is not None:
29 | self.callback(self)
30 | return
31 | elif value != '*':
32 | parameter.setInput(value, sender=sender)
33 | parameter.update()
34 | if self.callback is not None:
35 | self.callback(self)
36 |
37 | def setFree(self, sender):
38 | value = bool(sender.get())
39 | self.parameter.setFree(value)
40 |
41 | class ParameterTextInput(Group):
42 |
43 | def __init__(self, parameter, posSize, text='', callback=None, continuous=False, showRelativeValue=False):
44 | super(ParameterTextInput, self).__init__(posSize)
45 | self.parameter = parameter
46 | rel = self._relValue()
47 | self.callback = callback
48 | self.textInput = NumberEditText((0, 0, -40, -0), text=parameter.value, callback=self._valueInput, allowEmpty=False, continuous=continuous, decimals=1)
49 | self.relInfo = TextBox((-35, 5, -0, -0), rel, alignment='left', sizeStyle='small')
50 | self.showRelativeValue(showRelativeValue)
51 | self.vanillaInputs = [self.textInput]
52 | self.parameter.bind(self)
53 |
54 | def set(self, value):
55 | self.parameter.set(value)
56 | self.update(None)
57 |
58 | def get(self):
59 | return self.parameter.get()
60 |
61 | def enable(self, value):
62 | for item in self.vanillaInputs:
63 | item.enable(value)
64 |
65 | def _valueInput(self, sender):
66 | value = sender.get()
67 | parameter = self.parameter
68 | if value == 'R' and parameter.hasMaster:
69 | parameter.reset()
70 | parameter.update()
71 | if self.callback is not None:
72 | self.callback(self)
73 | return
74 | elif value != '*':
75 | if value == int(value): value = int(value)
76 | parameter.setInput(value, sender=sender)
77 | parameter.update()
78 | if self.callback is not None:
79 | self.callback(self)
80 | rel = self._relValue()
81 | self.relInfo.set(rel)
82 |
83 | def showRelativeValue(self, b):
84 | self.relInfo.show(b)
85 |
86 | def setFree(self, sender):
87 | value = bool(sender.get())
88 | self.parameter.setFree(value)
89 |
90 | def update(self, sender):
91 | value = self.parameter.get()
92 | self.textInput.set(value)
93 | self._updateRelValue()
94 |
95 | def _updateRelValue(self):
96 | rel = self._relValue()
97 | self.relInfo.set(rel)
98 |
99 | def _relValue(self):
100 | parameter = self.parameter
101 | rel = '-'
102 | if parameter.hasMaster:
103 | if parameter.mode == 'ratio':
104 | rel = '%s' % (parameter.getRatio())
105 | elif parameter.mode == 'offset':
106 | offsetValue = round(parameter.getOffset(), 1)
107 | sign = '+' if offsetValue >= 0 else ''
108 | rel = '%s%s' % (sign, offsetValue)
109 | return rel
110 |
111 | class ParameterSliderTextInput(Group):
112 |
113 | '''
114 | Custom Vanilla object consisting mainly of a Slider & and text input linked together (through a parameter object)
115 | '''
116 |
117 | def __init__(self, parameter, posSize, title=None, callback=None):
118 | super(ParameterSliderTextInput, self).__init__(posSize)
119 | self.parameter = parameter
120 | self.callback = callback
121 | editTextPosSize = (-65, 0, 40, 22)
122 | if title is None:
123 | sliderPosSize = (5, 3, -80, 15)
124 | elif title is not None:
125 | title = title.capitalize()
126 | sliderPosSize = (70, 3, -80, 15)
127 | self.title = TextBox((0, 3, 65, 30), title, sizeStyle='small')
128 | if parameter.dissociable:
129 | editTextPosSize = (-65, 0, 40, 22)
130 | self.checkBox = CheckBox((-22, 0, 22, 22), u'∞', callback=self.setFree, value=True, sizeStyle='mini')
131 | self.slider = Slider(sliderPosSize, minValue=parameter.limits[0], maxValue=parameter.limits[1], value=parameter.value, callback=self.valueInput, sizeStyle='small')
132 | self.textInput = NumberEditText(editTextPosSize, text=parameter.value, callback=self.valueInput, allowEmpty=False, continuous=False, sizeStyle='small')
133 | self.parameter.bind(self)
134 |
135 | def get(self):
136 | return self.parameter.get()
137 |
138 | def enable(self, b):
139 | self.slider.enable(b)
140 | self.textInput.enable(b)
141 | if hasattr(self, checkBox):
142 | self.checkBox.enable(b)
143 |
144 | def valueInput(self, sender):
145 | value = sender.get()
146 | parameter = self.parameter
147 | if value == 'R':
148 | parameter.reset()
149 | parameter.update()
150 | if self.callback is not None:
151 | self.callback(self)
152 | return
153 | elif value != '*':
154 | parameter.setInput(value, sender=sender)
155 | parameter.update()
156 | if self.callback is not None:
157 | self.callback(self)
158 |
159 | def update(self, sender):
160 | value = self.parameter.get()
161 | self.textInput.set(value)
162 | if (value != '*'):
163 | self.slider.set(value)
164 | if hasattr(self, 'checkBox'):
165 | free = self.parameter.hasMaster
166 | self.checkBox.set(free)
167 |
168 | def setFree(self, sender):
169 | value = not bool(sender.get())
170 | self.parameter.setFree(value)
171 |
172 | class VanillaParameterWrap(object):
173 |
174 | '''
175 | Base class, to be subclassed,
176 | making it easy to link a Parameter object
177 | with Vanilla UI input objects (Slider, EditText, CheckBox)
178 | '''
179 |
180 | def __init__(self):
181 | self.controls = []
182 | self.sender = None
183 | self.master = None
184 |
185 | def bind(self, vanillaObject):
186 | self.controls.append(vanillaObject)
187 |
188 | def unbind(self, vanillaObject):
189 | if vanillaObject in self.controls:
190 | self.controls.remove(vanillaObject)
191 |
192 | def updateControls(self):
193 | for vanillaObject in self.controls:
194 | vanillaObject.update(self.sender)
195 |
196 | class VanillaSingleValueParameter(SingleValueParameter, VanillaParameterWrap):
197 |
198 | '''
199 | Subclass implementing a link between a vanilla UI and parameter object
200 | '''
201 |
202 | def __init__(self, name, defaultValue=None, limits=None, numType='float', master=None, mode=None, enable=True, dissociable=False):
203 | VanillaParameterWrap.__init__(self)
204 | SingleValueParameter.__init__(self, name, defaultValue=defaultValue, limits=limits, numType=numType, master=master, mode=mode)
205 | self.enable = enable
206 | self.dissociable = dissociable
207 | self.formerMaster = None
208 |
209 | def setInput(self, value, sender):
210 | self.sender = sender
211 | self.set(value)
212 |
213 | def setFree(self, b):
214 | if b:
215 | self.formerMaster = self.master
216 | if self.master is not None:
217 | self.master.affranchise(self)
218 | self.master = None
219 | elif not b:
220 | if self.formerMaster is not None:
221 | self.master = self.formerMaster
222 | self.master.enslave(self)
223 |
224 | def update(self):
225 | self.relationValue = self._getRelationValue()
226 | self.propagate()
227 | self.updateControls()
228 |
229 |
--------------------------------------------------------------------------------
/source/lib/MutatorScale/Readme.md:
--------------------------------------------------------------------------------
1 | # MutatorScale
2 |
3 | Here’s an introduction to MutatorScale, a tool for interpolated glyph scaling, based on [FontParts](https://github.com/roboTools/fontParts), [FontTools](https://github.com/fontTools/fontTools), [MutatorMath](https://github.com/LettError/MutatorMath), [FontMath](https://github.com/typesupply/fontMath) & [BooleanOperations](https://github.com/typemytype/booleanOperations).
4 |
5 | It consists of a little set of objects — I wouldn’t go as far as to call it a library —, the most important and central one being what I call a *MutatorScaleEngine*.
6 |
7 | Its function is to build an interpolation design space, based on MutatorMath, with which it is rendered easier to scale glyphs while compensating for the loss of weight and/or contrast by interpolating. Such operations imply that you have at least two interpolatable fonts to begin with.
8 |
9 | Note: MutatorScale is used by the [ScaleFast](https://github.com/roboDocs/ScaleFast) extension.
10 |
11 | 
12 | 
13 |
14 | ## Overview
15 |
16 | Here’s how it goes. Providing you have a couple of interpolatable fonts, you can produce a wide range of derivative glyphs the design of which can be summed up as scaled down versions of others, the infamous example being small capitals. I’ll leave the ‘Small caps should be drawn’ purists to their romantic views and assume you’d love to hear more about generating small caps, among other things.
17 |
18 | You start by building a MutatorScaleEngine, feeding it fonts it can interpolate from:
19 |
20 | ```python
21 | scaler = MutatorScaleEngine(fonts)
22 | ```
23 |
24 | Next, you provide information about the scaling you wish to perform. This can go two ways. The first and most direct one:
25 |
26 | ```python
27 | scaler.set({ 'scale': 0.8 })
28 | ```
29 |
30 | At all times, the .set() method of a MutatorScaleEngine is fed a dictionary containing scaling information. The alternate way to define your scaling goes like this:
31 |
32 | ```python
33 | scaler.set({
34 | 'width': 1.03,
35 | 'referenceHeight': 'capHeight',
36 | 'targetHeight': 520
37 | })
38 | ```
39 |
40 | This way may seem less straightforward in terms of code but is closer to design. You provide the required meaningful proportions that allow the MutatorScaleEngine to compute scaling values.
41 |
42 | **width** corresponds to simple horizontal scaling and should be a float value akin to a percentage (100% == 1.0).
43 |
44 | **referenceHeight** can be either a string or a number (float or int), but if it is a string, it should be a height reference the master fonts will know about: vertical metrics.
45 |
46 | **targetHeight** is the height you wish to see your scaled glyphs have; should be a number (float or int).
47 |
48 | From these values, the MutatorScaleEngine computes proper scaling ratios. The interesting aspect in this approach is that the scaling ratios may vary among interpolation masters so that you can effectively interpolate glyphs from fonts with slightly different vertical metrics/proportions and still obtain scaled glyphs at the exact proportion you asked for — what it means concretely is that you could interpolate an ’H’ scaled down to 520 units in height from two master fonts with different capHeights.
49 |
50 | *****
51 |
52 | Once scale and fonts are set, the MutatorScaleEngine is ready to produce scaled glyphs, on demand.
53 |
54 | Now if we ask:
55 |
56 | ```python
57 | scaledGlyph = scaler.getScaledGlyph('H', stems)
58 | ```
59 |
60 | We get a new scaled letter H.
61 |
62 | With **glyphName** (‘H’, ‘a’, etc.), I’ve also provided a **stems** variable and it is a crucial part of the process, so I’ll elaborate on that.
63 |
64 | When a MutatorScaleEngine is given master fonts, it does a quick analysis to be able to place them in an interpolation space. It measures reference stems for each font so that you can later ask for scaled glyphs with a specific stem value. Working with stem values is arbitrary and you can actually override this if you’d rather work with some other values that are more meaningful to you, but I’ll get into that later on.
65 |
66 | Stems are measured on uppercase I and H, to get both a vertical and horizontal stem value of reference.
67 |
68 | As reference values are based on an H’s vertical and horizontal stems, you should use these as a reference when you scale glyphs and ask for specific stem values.
69 |
70 | In effect, if you ask:
71 |
72 | ```python
73 | scaler.getScaledGlyph('H', (100, 20))
74 | ```
75 |
76 | You’re asking for a scaled glyph ‘H’ that has 100 units for its vertical stems and 20 for its horizontal stems. If you ask for another glyph with these same values, you’re not asking to obtain that specific glyph with exactly these stem values but you’re asking for a scaled glyph, say ‘A’, with stems as they should consistently be next to an H with stem values of 100 and 20.
77 |
78 | ## Going Deeper
79 |
80 | Here I’ll focus on what’s happening inside a MutatorScaleEngine. As the name indicates, I got the idea from playing around with MutatorMath, and MutatorScale depends totally on MutatorMath’s mojo.
81 |
82 | To understand how glyphs are scaled down and corrected, you should first grasp how MutatorMath functions even if it’s just a general understanding.
83 |
84 | The whole point of MutatorMath is to define a design space for interpolation. The word *space* is meant quite literally here because one of the key objects of MutatorMath is a **Location**.
85 | With well defined key Locations (= masters), you obtain an axis on which you can move and retrieve interpolated data.
86 |
87 | Quite often with glyph interpolation, we use Location values that correspond to some weight pacing system (0 to 1000, 100 Thin, 300 Light, 400 Regular, etc.). But the numbers you use for locations can be anything. In MutatorScale I used stem values because that’s the thing I wanted to keep track of. If you build a mutator with stem values, you can effectively ask for an interpolated glyph with specific stem values.
88 |
89 | On top of MutatorMath, the only thing done by a MutatorScaleEngine is to use an interpolation space containing scaled glyphs, defining these as master Locations by their scaled stem values, and allowing you to retrieve instance glyphs with unscaled stem values.
90 |
91 | Let’s say I have two masters, a Regular and a Bold. In the regular weight, an H’s vertical stem is 100 units wide, and in the bold weight, 200 units. If I’d like to obtain a regular small capital H with vertical stems of 100 units, scaled down 85% in width and 80% in height, here’s what I have to do around MutatorMath:
92 |
93 | 
94 |
95 | ```python
96 | # Scale down master glyphs to 0.85 width and 0.8 height
97 | regular_H.scale((0.85, 0.8))
98 | bold_H.scale((0.85, 0.8))
99 |
100 | # Calculate scaled down stem values
101 | scaled_regularStem = 100 * 0.85 # = 85
102 | scaled_boldStem = 200 * 0.85 # = 170
103 |
104 | # List masters with scaled glyph and scaled stem values
105 | masters = [
106 | ( Location(stem=scaled_regularStem), regular_H ),
107 | ( Location(stem=scaled_boldStem), bold_H )
108 | ]
109 |
110 | # Build a mutator of these scaled elements
111 | b, mutator = buildMutator(masters)
112 |
113 | # Ask for an instance of a scaled glyphs with an unscaled stem value, 100 for regular
114 | smallH = mutator.getInstance( Location(stem=100) )
115 | ```
116 |
117 | Now we retrieved a scaled down ‘H’ glyph with weight identical to a unscaled ‘H’, and that’s the basic operation happening inside of a MutatorScaleEngine.
118 |
119 | ## Types of interpolation
120 |
121 | A MutatorScaleEngine will switch from one interpolation type to another according to the fonts you provide and the stem values you’re asking for.
122 |
123 | The most basic mode is isotropic, it happens if you provide a single value for stems:
124 |
125 | ```python
126 | scaler.getScaledGlyph('H', 100)
127 | ```
128 |
129 | Although it’s a start — and in occasional cases, a finish — it will often fall short of achieving the desired result. Mostly because serifs/thins will be too meagre.
130 |
131 | You can get better result if you work with anisotropic interpolation, providing two values:
132 |
133 | ```python
134 | scaler.getScaledGlyph('H', (100, 20))
135 | ```
136 |
137 | But you should be aware that this can lead to ugly deformations if pushed too far; it’s not an ideal solution. Still, used with reason, it can produce close to final results with some designs.
138 |
139 | *(When you go too far with anisotropic interpolation)*
140 | 
141 |
142 | Last but not least, the scaling is best done with masters for both weight and contrast. This is the use case in which you will get results that require very little or no correction at all, most of the time. A MutatorScaleEngine determines by itself if conditions are met to interpolate on two axes rather than anisotropically.
143 |
--------------------------------------------------------------------------------
/source/html/index.md:
--------------------------------------------------------------------------------
1 | ScaleFast
2 | =========
3 |
4 | This extension’s mission is simple: keep stem widths consistent while you fiddle with proportions of a glyph. It manages that by trying to compensate for scale deformations through interpolation. To achieve this result, it requires at least two masters (a regular and a bold for instance). This way, you can easily produce scaled versions of existing glyph for any purpose you see fit, small capitals, superiors, extended or condensed styles, etc.
5 | Any transformation you input can be saved as a preset for a later use. Presets are stored inside the ufo file of the selected working font (among masters).
6 |
7 | *The tool’s flexibility comes a great deal from its relying on [MutatorMath](https://github.com/LettError/MutatorMath), written by Erik van Blokland.*
8 |
9 | 
10 | 
11 | 
12 | 
13 |
14 | ## Table of Contents
15 |
16 | - [How it works](#how-it-works)
17 | - [Scaling](#scaling)
18 | - [Stems](#stems)
19 | - [Modes](#modes)
20 | - [Presets](#presets)
21 | - [Guides](#guides)
22 | - [Transformations](#transformations)
23 | - [Offset](#offset)
24 | - [Sticky](#sticky)
25 | - [Tracking](#tracking)
26 | - [Generating](#generating)
27 | - [Current](#current)
28 | - [Batch](#batch)
29 |
30 | ## How it works
31 |
32 | To get the best possible results, here are a few explanations about how this extension works.
33 |
34 | The scaling is handled by a [scaling engine](https://github.com/loicsander/MutatorScale). When provided with fonts as masters, the scaling engine uses interpolation to scale glyphs according to settings defined by the user. In ScaleFast, adding or removing masters to the scaling engine is done by checking/unchecking the available fonts in the masters list.
35 |
36 | When you add masters (as many as you like), they are analyzed for vertical & horizontal stem width (based on capital I’s stem and the horizontal bar of H). These values are then used as reference points to build an interpolation space (with help of MutatorMath). If you don’t wish to work with stem values, you can replace them and work with units on any scale you like (0 to 1000 for instance). You should note however that this tool is built to work with stem widths, so if you work outside of this scheme, the script will work fine, but the experience won’t be as smooth.
37 |
38 | ## Scaling
39 |
40 | With ScaleFast, what you scale firstly are reference heights. This is why you’ll find a slider and text input requiring a value in units (per em) and a popup menu with predefined reference heights. What you’re asking for when you input [xHeight]>[300] is effectively that ScaleFast reduces glyphs with a ratio of 300/500, if the xHeight is 500 units high, for instance. The ratio part is taken care of, all you need to know is the change in dimensions you want. This specific input used as an example will result in lowercase letters having a 300 units high xHeight themselves.
41 |
42 | ### Stems
43 |
44 | As I mentioned earlier, the whole point of ScaleFast is allowing you to scale glyphs while defining the exact stem width (be it vertical or horizontal) you wish to obtain on the scaled glyphs. This being, be aware that scaled glyphs go through quite a lot of mathematical operations and rounding, so don’t be surprised if the results display some little inaccuracies (shouldn’t be beyond 2 or 3 units though).
45 | The way you define stem values depends on the mode you’re working with.
46 |
47 | ### Modes
48 |
49 | ScaleFast can work according to three modes, the default being isotropic.
50 |
51 | **Isotropic**
52 |
53 | This is the simplest interpolation, one that moves values linearly between two reference points, or masters. With this mode, the script will only be able to retain vertical stem width while you scale glyphs; which is not so bad to begin with. This means that serif thickness, for instance, will be smaller than the original size. With this mode, you can only define vertical stem values, which will define the interpolation factor between master stem values. If the masters stem values are accurate, the result will be as well. Only vertical stem width will be correct though.
54 |
55 | **Anisotropic**
56 |
57 | The anisotropic mode distinguishes interpolation on the X and Y axes. It provides the possibility of deformation along each of those two axes. Practically, it means that — to a certain extent — the script can compensate for reduction on the Y axis also and try to maintain horizontal stem width as well. Depending on the design, you might luckily not need to correct serif thickness or contrast. This mode requires two values for vertical and horizontal stems, with that and to the best of its capabilities, the tool will try to maintain these values for the stems of the scaled glyphs. Be aware that the result will strongly depend on your design, if you spot inconsistencies in size among the generated glyphs, please start by checking that these aren’t due to your masters’ stem widths.
58 |
59 | **Bi-dimensional**
60 |
61 | Being able to work in two-dimensional interpolation was the actual reason that pushed me to write this tool. Thanks to MutatorMath, handling interpolation along multiple axis has become incredibly easy, and it’s also incredibly powerful. The best use case (and the one I initially wrote this tool for) is the case of a contrasted type family with optical sizes. For type of which the weight evolves in the ‘usual’ way — that is to say relative contrast lessens while weight becomes heavier, effectively making horizontal stems thicker — working with isotropic or anisotropic interpolation will probably be sufficient to generate scaled glyphs that require little or no correction.
62 |
63 | But in the case of a family in which the thickness thin parts (serifs for instance) do not change with weight (random example: a Didot face), anisotropic interpolation can’t compensate anything because there’s no difference in contrast to work from. But if you have been working with optical sizes and your optical sizes are compatible for interpolation, then you do have a difference in contrast that can be put to good use. This situation allows you to work both with separate weight & contrast axes, and in that case you can use bi-dimensional interpolation to solve your scaling problems. To be honest, you could work out an an/isotropic interpolation scheme with your optical sizes, but that would be to the expense of much time spent generating intermediary masters. Not very practical.
64 |
65 | Now back to ScaleFast, if you provide at least three masters that allow the script to build a two axis interpolation scheme, then you can generate whatever scaled glyphs you need, and it’s actually the case in which the tool performs the best.
66 |
67 | To be more specific, this mode requires that at least two masters both share their horizontal stem values while having different vertical stem values, and that a a least one third master has an horizontal stem value different from the two others.
68 | But don’t bother keeping that in mind, ScaleFast figures out on its own if it has all that is required for bi-dimensional interpolation, it will switch automatically to this mode if it can.
69 |
70 | ### Presets
71 |
72 | Any settings you define can be store as a preset (through the right hand panel). Presets are stored in the selected working font, so they will stay in the UFO unless you remove them.
73 |
74 | 
75 | 
76 | 
77 |
78 | ### Guides
79 |
80 | You can add custom guides that will be stored in the font and can be displayed to help with your scaling work.
81 |
82 | ## Transformations
83 |
84 | ### Offset
85 |
86 | On top of the scaling, you can defined X/Y offsets to be applied to all glyphs.
87 |
88 | ### Sticky
89 |
90 | In combination with manual offsetting, there’s a helper ‘sticky’ option that allows you to define alignments for scaled glyph. If you’re working on superiors for instance and you wish to see them aligned with the capHeight, you only need to specify [top][capHeight]. Note that the second Pop-up menu will recognize any custom guide as well as the base vertical metrics of a font.
91 |
92 | ### Tracking
93 |
94 | There are several things you can do about the spacing of the glyphs you scale. By default, the width of a scaled glyph is scaled as well. But if you’d rather avoid that, you can activate the ‘Keep inital sidebearings’ checkbox, the glyphs will be scaled but their sidebearings will remain those of the normally sized glyphs (using the source glyph of the selected master font as reference).
95 | On top of that — spacing being scaled or not — you can add tracking, either in percentage or units (per em). Note that if you apply tracking with percentages, you will probably get undesired results with components (because handling those is rather tricky); it will work great for glyphs containing only contours though.
96 |
97 | ## Generating
98 |
99 | You can generate any glyph set you want. The generated glyphs can then be directly reinserted into one of the existing masters, or another open font, or a new one created for the occasion. Additionally, you can suffix the generated glyphs. Note that if you reinsert generated glyphs in a existing font without suffixing glyph names, existing glyphs with the same name in the target font will be replaced.
100 |
101 | ### Current
102 |
103 | This generates glyphs with the current settings and provided glyphset + suffix.
104 |
105 | ### Batch
106 |
107 | You can also generate different glyphsets by using presets to define which settings should be applied to a specific series of glyphs.
108 |
109 | 
110 | 
111 |
--------------------------------------------------------------------------------
/source/lib/dynamicParameters/lib/dynamicParameters/baseParameter.py:
--------------------------------------------------------------------------------
1 | #coding=utf-8
2 | # Loïc Sander — 2014
3 | from __future__ import division
4 | import re
5 |
6 | class ParameterModeError(Exception):
7 |
8 | msg = "A slave parameter's mode cannot be"
9 |
10 | def __init__(self, mode):
11 | self.mode = mode
12 |
13 | def __str__(self):
14 | return '%s %s' % (self.msg, repr(self.mode))
15 |
16 | class ParameterValueError(Exception):
17 |
18 | msg = "A parameter needs a default value or master."
19 |
20 | def __str__(self):
21 | return '%s' % (self.msg)
22 |
23 | def valueToRatio(referenceValue, value, rounding=8):
24 | if referenceValue:
25 | return round((value/referenceValue), rounding)
26 | return 1
27 |
28 | def ratioToValue(reference, ratio, rounding=8):
29 | return round(reference * ratio, rounding)
30 |
31 | class SingleValueParameter(object):
32 |
33 | '''
34 | Base parameter object built to connect numerical values
35 | on a _ratio_ or _offset_ basis, dynamically.
36 | '''
37 |
38 | def __init__(self, name, defaultValue=None, limits=None, numType='float', master=None, mode=None):
39 | self.name = name
40 | self.master = master
41 | if (master is None) and (defaultValue is None):
42 | raise ParameterValueError
43 | return
44 | if (master is None) and (defaultValue is not None):
45 | self.value = defaultValue
46 | elif (master is not None):
47 | self.value = master.get()
48 | self.mode = mode
49 | self.numType = numType
50 | self.validModes = ['ratio', 'offset']
51 | self.limits = limits
52 | if master is not None:
53 | master.slaves.append(self)
54 | if mode not in self.validModes:
55 | raise ParameterModeError(mode)
56 | return
57 | self.limits = master.limits
58 | self.relationValue = self._getRelationValue()
59 | self.slaves = []
60 | self.defaultValue = defaultValue
61 |
62 | def __repr__(self):
63 | if self.master is not None: master = self.master.name
64 | else: master = None
65 | return '' % (self.name, self.value, master, self.mode)
66 |
67 | def __add__(self, other):
68 | return self.mathOperate(other, 'add')
69 |
70 | __radd__ = __add__
71 |
72 | def __sub__(self, other):
73 | return self.mathOperate(other, 'sub')
74 |
75 | __rsub__ = __sub__
76 |
77 | def __mul__(self, other):
78 | return self.mathOperate(other, 'mul')
79 |
80 | __rmul__ = __mul__
81 |
82 | def __div__(self, other):
83 | return self.mathOperate(other, 'div')
84 |
85 | __rdiv__ = __rtruediv__ = __truediv__ = __div__
86 |
87 | def __eq__(self, other):
88 | if isinstance(other, self.__class__):
89 | return (self.name == other.name) and (self.mode == other.mode) and (self.master == other.master) and (self.limits == other.limits) and (self.numType == other.numType)
90 | return False
91 |
92 | def mathOperate(self, other, operation):
93 | firstValue = self.get()
94 | secondValue = None
95 | if self.__class__ == other.__class__:
96 | secondValue = other.get()
97 | elif isinstance(other, (float, int)):
98 | secondValue = other
99 | if secondValue is not None:
100 | p = self.clone()
101 | if operation == 'add':
102 | value = firstValue + secondValue
103 | elif operation == 'sub':
104 | value = firstValue - secondValue
105 | elif operation == 'mul':
106 | value = firstValue * secondValue
107 | elif operation == 'div':
108 | value = firstValue / secondValue
109 | p.set(value)
110 | return p
111 | else:
112 | raise TypeError
113 |
114 | def clone(self):
115 | return self.__class__(self.name, self.defaultValue, self.limits, self.numType, self.master, self.mode)
116 |
117 | def asDict(self):
118 | return dict(
119 | name = self.name,
120 | numType = self.numType,
121 | limits = self.limits,
122 | master = self.master,
123 | defaultValue = self.defaultValue,
124 | mode = self.mode,
125 | value = self.value
126 | )
127 |
128 | def asShortDict(self):
129 | return dict(name = self.name, value = [self.value, self.master])
130 |
131 | def digest(self):
132 | d = []
133 | d.append('Parameter: %s'%(self.name))
134 | d.append('Value: %s'%(self.get()))
135 | if (self.master is not None) and (self.mode is not None):
136 | d.append('mode: %s'%(self.mode))
137 | d.append('ratio: %s'%(self.getRatio()))
138 | d.append('offset: %s'%(self.getOffset()))
139 | d.append('Master: %s [%s]'%(self.master.name, self.master.get()))
140 | d.append('\n')
141 | return '\n'.join(d)
142 |
143 | def set(self, value):
144 | self.value = self._checkValue(value)
145 | if self.master is not None:
146 | self.relationValue = self._getRelationValue()
147 | self.propagate()
148 |
149 | def setRatio(self, ratio):
150 | if self.master is not None:
151 | self.value = ratioToValue(self.master.get(), ratio)
152 | self.relationValue = self._getRelationValue()
153 | self.propagate()
154 |
155 | def setOffset(self, offset):
156 | if self.master is not None:
157 | self.value = self.master.get() + offset
158 | self.relationValue = self._getRelationValue()
159 | self.propagate()
160 |
161 | def setMode(self, mode):
162 | if mode in self.validModes:
163 | self.mode = mode
164 | self.update()
165 |
166 | def get(self):
167 | master = self.master
168 | mode = self.mode
169 | if (master is not None) and (mode is not None):
170 | relationValue = self.relationValue
171 | if mode == 'ratio':
172 | value = ratioToValue(master.get(), relationValue)
173 | elif mode == 'offset':
174 | value = master.get() + relationValue
175 | elif (master is None):
176 | value = self.value
177 |
178 | return self._constrainValue(value)
179 |
180 | def getRatio(self):
181 | if self.master is not None:
182 | masterValue = self.master.get()
183 | value = self.value
184 | return valueToRatio(masterValue, value)
185 | return 1
186 |
187 | def getOffset(self):
188 | if self.master is not None:
189 | masterValue = self.master.get()
190 | value = self.value
191 | return self._formatValue(value - masterValue)
192 | return 0
193 |
194 | def _getRelationValue(self):
195 | if self.mode == 'ratio':
196 | ratio = self.getRatio()
197 | return ratio
198 | elif self.mode == 'offset':
199 | offset = self.getOffset()
200 | return offset
201 | return
202 |
203 | def getInt(self):
204 | return int(round(self.get()))
205 |
206 | def update(self):
207 | self.relationValue = self._getRelationValue()
208 | self.propagate()
209 |
210 | def propagate(self):
211 | for slave in self.slaves:
212 | slave.value = slave.get()
213 | slave.update()
214 |
215 | def reset(self):
216 | master = self.master
217 | if master is None:
218 | self.value = self.defaultValue
219 | elif master is not None:
220 | self.value = master.get()
221 | self.relationValue = self._getRelationValue()
222 |
223 | def setDefault(self, value):
224 | value = self._checkValue(value)
225 | if value is not None:
226 | self.defaultValue = value
227 |
228 | def getDefault(self):
229 | if self.master is None:
230 | return self.defaultValue
231 | elif self.master is not None:
232 | return self.master.get()
233 |
234 | def enslave(self, parameter):
235 | if parameter not in self.slaves:
236 | if parameter.mode in ['ratio', 'offset']:
237 | self.slaves.append(parameter)
238 | parameter.master = self
239 | parameter.relationValue = parameter._getRelationValue()
240 | parameter.limits = self.limits
241 | parameter.value = parameter.get()
242 | parameter.update()
243 | else:
244 | raise ParameterModeError(mode)
245 |
246 | def affranchise(self, slave):
247 | if slave in self.slaves:
248 | self.slaves.remove(slave)
249 |
250 | def setMaster(self, master):
251 | # if this parameter already has a master
252 | # free it first
253 | if self.master is not None:
254 | self.master.affranchise(self)
255 | if master is not None:
256 | master.enslave(self)
257 | elif master is None:
258 | self.master = None
259 |
260 | @property
261 | def hasMaster(self):
262 | return self.master is not None
263 |
264 | def setLimits(self, minMaxValues):
265 | self.limits = minMaxValues # (minValue, maxValue)
266 | for slave in self.slaves:
267 | slave.limits = minMaxValues # (minValue, maxValue)
268 | slave.value = slave.get()
269 | slave.update()
270 |
271 | def _checkValue(self, value):
272 | if isinstance(value, str):
273 | s = re.search(r'(\+\+|--)(\d*\.?\d*)', value)
274 | if s is not None:
275 | offset = float(s.group(2))
276 | if s.group(1) == '++':
277 | value = self.get() + offset
278 | elif s.group(1) == '--':
279 | value = self.get() - offset
280 | elif s is None:
281 | try: value = float(value)
282 | except: value = self.get()
283 | return self._constrainValue(value)
284 | elif isinstance(value, float) or isinstance(value, int):
285 | return self._constrainValue(value)
286 | return
287 |
288 | def _constrainValue(self, value):
289 | limits = self.limits
290 | if limits is not None:
291 | minValue, maxValue = limits
292 | if value < minValue: value = minValue
293 | elif value > maxValue: value = maxValue
294 | return self._formatValue(value)
295 |
296 | def _formatValue(self, value):
297 | if self.numType == 'int':
298 | value = int(round(value))
299 | elif self.numType == 'float':
300 | if value == int(value):
301 | value = int(value)
302 | else:
303 | value = round(value, 2)
304 | return value
305 |
306 | # Testing stuff
307 | # fontWeight = SingleValueParameter('fontWeight', 80, (1,500), 'int')
308 | # capWeight = SingleValueParameter('capWeight', 100, (1,500), 'int', mode='ratio', master=fontWeight)
309 | # smallCapsWeight = SingleValueParameter('smallCapsWeight', 90, (1,500), 'int', mode='ratio', master=fontWeight)
310 |
311 | # fontWeight.set(100)
312 |
313 | # print fontWeight.digest()
314 | # print capWeight.digest()
315 | # print smallCapsWeight.digest()
316 |
--------------------------------------------------------------------------------
/source/lib/MutatorScale/lib/mutatorScale/objects/fonts.py:
--------------------------------------------------------------------------------
1 | #coding=utf-8
2 | from __future__ import division
3 |
4 | try:
5 | import mutatorScale
6 | except:
7 | import os
8 | import sys
9 | libFolder = os.path.dirname(os.path.dirname(os.getcwd()))
10 | if not libFolder in sys.path:
11 | sys.path.append(libFolder)
12 |
13 | from mutatorScale.objects.mathGlyph import MathGlyph
14 | from mutatorScale.utilities.fontUtils import makeListFontName, getRefStems, getSlantAngle
15 |
16 | from fontTools.pens.boundsPen import BoundsPen
17 |
18 | class ScaleFont(object):
19 | """
20 | A ScaleFont takes a font object (FontParts or Defcon) and a scale setting,
21 | it is then ready to return any number of scaled glyphs.
22 |
23 | Usage:
24 | smallFont = ScaleFont(font, 0.5)
25 | small_Glyph_A = smallFont.getGlyph('A')
26 | Or:
27 | smallFont = ScaleFont(font)
28 | smallFont.setScale((1.05, 490, 'capHeight'))
29 | """
30 | def __init__(self, font, scale=None):
31 | self.glyphSet = {glyph.name:glyph for glyph in font}
32 | self.scale = scale
33 | self.heights = { heightName:getattr(font.info, heightName) for heightName in ['capHeight','ascender','xHeight','descender'] }
34 | self.name = makeListFontName(font)
35 | self.italicAngle = -getSlantAngle(font, True)
36 |
37 | if scale is not None:
38 | self.setScale(scale)
39 |
40 | def __repr__(self):
41 | return '<{className} {fontName}>'.format(className = self.__class__.__name__, fontName = self.name)
42 |
43 | def __getitem__(self, key):
44 | return self.getGlyph(key)
45 |
46 | def __contains__(self, glyphName):
47 | return glyphName in self.glyphSet
48 |
49 | def keys(self):
50 | return self.glyphSet.keys()
51 |
52 | def getXScale(self):
53 | if self.scale is not None:
54 | return self.scale[0]
55 | return
56 |
57 | def getYScale(self):
58 | if self.scale is not None:
59 | return self.scale[1]
60 | return
61 |
62 | def getScale(self):
63 | return self.scale
64 |
65 | def setScale(self, scale):
66 | """ Setting scale for the font.
67 |
68 | – Either a simple (x, y) scale tuple;
69 | – or a tuple in the form (width, targetHeight, referenceHeight).
70 | – x, y, width should be floats;
71 | – targetHeight should be an int or float;
72 | – referenceHeight can be either a string or float/int.
73 | """
74 | if len(scale) == 2:
75 | self.scale = scale
76 |
77 | elif len(scale) == 3:
78 | x, targetHeight, referenceHeight = scale
79 |
80 | try:
81 | xy = targetHeight / referenceHeight
82 |
83 | except:
84 |
85 | # try parsing referenceHeight to a numeric value
86 | if referenceHeight in self.heights:
87 | referenceHeightValue = self.heights[referenceHeight]
88 | elif referenceHeight in self.glyphSet:
89 | referenceHeightValue = self._getGlyphHeight(referenceHeight)
90 | if referenceHeightValue is None:
91 | referenceHeightValue = targetHeight
92 | else:
93 | referenceHeightValue = referenceHeight
94 |
95 | # try parsing targetHeight to a numeric value
96 | if targetHeight in self.heights:
97 | targetHeightValue = self.heights[targetHeight]
98 | elif targetHeight in self.glyphSet:
99 | targetHeightValue = self._getGlyphHeight(targetHeight)
100 | else:
101 | targetHeightValue = targetHeight
102 |
103 | try:
104 | xy = targetHeightValue / referenceHeightValue
105 | except:
106 | xy = 1
107 |
108 | finally:
109 | self.scale = (x * xy, xy)
110 |
111 | def _getGlyphHeight(self, glyphName):
112 | box = self._getGlyphBounds(glyphName)
113 | if box is not None:
114 | xMin, yMin, xMax, yMax = box
115 | return yMax - yMin
116 | return
117 |
118 | def _getGlyphBounds(self, glyphName):
119 | glyph = self.glyphSet[glyphName]
120 | pen = BoundsPen(self.glyphSet)
121 | glyph.draw(pen)
122 | return pen.bounds
123 |
124 | def getGlyph(self, glyphName):
125 | """Return a scaled glyph as a MathGlyph instance."""
126 | if glyphName in self.glyphSet:
127 | glyph = self.glyphSet[glyphName]
128 | scale = self.scale
129 | scaledGlyph = self._scaleGlyph(glyph, scale)
130 | return scaledGlyph
131 | else:
132 | return KeyError
133 |
134 | def extractGlyph(self, glyphName, glyph):
135 | scaledGlyph = self.getGlyph(glyphName)
136 | for attribute in ['name','unicodes','width']:
137 | setattr(glyph, attribute, getattr(scaledGlyph, attribute))
138 | pen = glyph.getPen()
139 | scaledGlyph.draw(pen)
140 |
141 | def _scaleGlyph(self, glyph, scale):
142 | """
143 | Return a glyph scaled according to the font’s scale settings,
144 | if glyph has components, reset scaling on each component but keep scaled offset coordinates.
145 | """
146 | glyph = MathGlyph(glyph)
147 | italicAngle = self.italicAngle
148 | # Skew to an upright position to prevent the slant angle from changing because of scaling
149 | if italicAngle:
150 | glyph.skewX(italicAngle)
151 |
152 | # Do the scaling
153 | glyph *= scale
154 | # Cancel scaling effect on components
155 | for i, component in enumerate(glyph.components):
156 | baseGlyph, matrix = component
157 | xx, yx, xy, yy, x, y = matrix
158 | xx, yx, xy, yy = 1, 0, 0, 1
159 | glyph.components[i] = (baseGlyph, (xx, yx, xy, yy, x, y))
160 | # Reverting to initial slant angle
161 | if italicAngle:
162 | glyph.skewX(-italicAngle)
163 |
164 | return glyph
165 |
166 | class MutatorScaleFont(ScaleFont):
167 | """ Subclass extending a ScaleFont and adding reference stem values to be used inside a MutatorScaleEngine."""
168 |
169 | def __init__(self, font, scale=(1, 1), vstem=None, hstem=None, stemsWithSlantedSection=False):
170 | super(MutatorScaleFont, self).__init__(font, scale)
171 | self._refVstem, self._refHstem = None, None
172 | self.stemsWithSlantedSection = stemsWithSlantedSection
173 | self.processDimensions(font, vstem, hstem)
174 |
175 | def __repr__(self):
176 | return '<{className} {fontName} v:{vstem} h:{hstem}>'.format(className=self.__class__.__name__, fontName=self.name, vstem=self._refVstem, hstem=self._refHstem)
177 |
178 | def processDimensions(self, font, vstem, hstem):
179 | if vstem is None and hstem is None:
180 | refVstem, refHstem = getRefStems(font, self.stemsWithSlantedSection)
181 | self._refVstem, self._refHstem = refVstem, refHstem
182 | elif hstem is None:
183 | self._refVstem = vstem
184 | self._refHstem = vstem
185 | else:
186 | self._refVstem = vstem
187 | self._refHstem = hstem
188 |
189 |
190 | def getStems(self):
191 | return self.vstem, self.hstem
192 |
193 | def setStems(self, stems):
194 | vstem, hstem = stems
195 | self.vstem = vstem
196 | self.hstem = hstem
197 |
198 | @property
199 | def vstem(self):
200 | return self._refVstem
201 | @vstem.setter
202 | def vstem(self, stem):
203 | self._refVstem = stem
204 |
205 | @property
206 | def hstem(self):
207 | return self._refHstem
208 | @hstem.setter
209 | def hstem(self, stem):
210 | self._refHstem = stem
211 |
212 | if __name__ == '__main__':
213 |
214 | import unittest
215 | import os
216 | from time import time
217 | from defcon import Font
218 |
219 | class ScaleFontsTest(unittest.TestCase):
220 |
221 | def setUp(self):
222 | self.glyphNames = ['H', 'Aacute', 'A', 'O', 'B']
223 | libFolder = os.path.dirname(os.path.dirname((os.path.dirname(os.path.abspath(__file__)))))
224 | singleFontPath = u'testFonts/two-axes/regular-low-contrast.ufo'
225 | fontPath = os.path.join(libFolder, singleFontPath)
226 | font = Font(fontPath)
227 | self.smallFont = ScaleFont(font, (0.5, 0.4))
228 | self.stemedSmallFont = MutatorScaleFont(font, (0.5, 0.4))
229 | self.stemedSmallFont = MutatorScaleFont(font, (0.5, 0.4), stemsWithSlantedSection=True)
230 | self.stemedSmallFont = MutatorScaleFont(font, (0.5, 0.4), vstem=100, stemsWithSlantedSection=True)
231 | self.stemedSmallFont = MutatorScaleFont(font, (0.5, 0.4), vstem=120, hstem=140, stemsWithSlantedSection=True)
232 |
233 | def test_setScale_with_values(self):
234 | """Test changing scale with x, y values."""
235 | for testFont in [self.smallFont, self.stemedSmallFont]:
236 | testFont.setScale((0.85, 0.79))
237 |
238 | def test_setScale_with_references(self):
239 | """Test changing scale with width, targetHeight, referenceHeight arguments."""
240 | for testFont in [self.smallFont, self.stemedSmallFont]:
241 | testFont.setScale((1.02, 450, 'capHeight'))
242 | testFont.setScale((0.65, 350, 250))
243 | testFont.setScale((1, 400, 'A'))
244 |
245 | def test_get_scaled_glyph_as_MathGlyph(self):
246 | """Test scaled glyph retrieval."""
247 | for testFont in [self.smallFont, self.stemedSmallFont]:
248 | for glyphName in self.glyphNames:
249 | scaledGlyph = testFont.getGlyph(glyphName)
250 | self.assertIsInstance(scaledGlyph, MathGlyph)
251 | scaledGlyph = testFont[glyphName]
252 | self.assertIsInstance(scaledGlyph, MathGlyph)
253 |
254 | def test_extract_scaled_glyph_as_Defcon_Glyph(self):
255 | """Test scaled glyph retrieval as a Defcon glyph."""
256 | from defcon import Glyph
257 | for testFont in [self.smallFont, self.stemedSmallFont]:
258 | scaledGlyph = Glyph()
259 | for glyphName in self.glyphNames:
260 | testFont.extractGlyph(glyphName, scaledGlyph)
261 | self.assertIsInstance(scaledGlyph, Glyph)
262 | self.assertEqual(scaledGlyph.name, glyphName)
263 |
264 | def test_extract_scaled_glyph_as_FontParts_Glyph(self):
265 | """Test scaled glyph retrieval as a FontParts Glyph."""
266 | from fontParts.fontshell import RGlyph
267 | for testFont in [self.smallFont, self.stemedSmallFont]:
268 | scaledGlyph = RGlyph()
269 | for glyphName in self.glyphNames:
270 | testFont.extractGlyph(glyphName, scaledGlyph)
271 | self.assertIsInstance(scaledGlyph, RGlyph)
272 |
273 | def test_set_stems(self):
274 | """Test setting stems on a MutatorScaleFont."""
275 | self.stemedSmallFont.setStems((100, 40))
276 |
277 | def test_set_stems_separately(self):
278 | """Test setting stems separately on a MutatorScaleFont."""
279 | self.stemedSmallFont.vstem = 120
280 | self.stemedSmallFont.hstem = 50
281 |
282 | unittest.main()
--------------------------------------------------------------------------------
/source/lib/MutatorScale/lib/mutatorScale/utilities/fontUtils.py:
--------------------------------------------------------------------------------
1 | #coding=utf-8
2 | from __future__ import division
3 | from math import atan2, tan, hypot, cos, degrees, radians
4 |
5 | from fontParts.fontshell import RGlyph
6 |
7 | import fontTools
8 | import fontTools.misc.bezierTools as bezierTools
9 | import fontTools.misc.arrayTools as arrayTools
10 | import fontTools.misc.transform as transform
11 | from fontTools.pens.boundsPen import BoundsPen
12 |
13 | try:
14 | import mutatorScale
15 | except:
16 | import os
17 | import sys
18 | libFolder = os.path.dirname(os.path.dirname(os.getcwd()))
19 | if not libFolder in sys.path:
20 | sys.path.append(libFolder)
21 |
22 | from mutatorScale.pens.utilityPens import CollectSegmentsPen
23 |
24 | def makeListFontName(font):
25 | """
26 | Return a font name in the form: 'Family name — style name'.
27 | The separator allows to easily split this full name later on with name.split(' — ').
28 | """
29 | familyName = font.info.familyName
30 | styleName = font.info.styleName
31 | if familyName is None:
32 | familyName = font.info.familyName = 'Unnamed'
33 | if styleName is None:
34 | styleName = font.info.styleName = 'Unnamed'
35 | return joinFontName(familyName, styleName)
36 |
37 |
38 | def joinFontName(familyName, styleName):
39 | separator = '-'
40 | return '{familyName} {separator} {styleName}'.format(familyName=familyName, separator=separator, styleName=styleName)
41 |
42 |
43 | def getRefStems(font, slantedSection=False):
44 | """
45 | Looks for stem values to serve as reference for a font in an interpolation scheme,
46 | only one typical value is returned for both horizontal and vertical stems.
47 | The method intersets the thick stem of a capital I and thin stem of a capital H.
48 | """
49 | stems = []
50 | angle = getSlantAngle(font, True)
51 |
52 | for i, glyphName in enumerate(['I','H']):
53 |
54 | if glyphName in font:
55 |
56 | baseGlyph = font[glyphName]
57 |
58 | # removing overlap
59 | glyph = freezeGlyph(baseGlyph)
60 | width = glyph.width
61 |
62 | glyph.skewBy((-angle, 0))
63 |
64 | xMin, yMin, xMax, yMax = getGlyphBox(glyph)
65 | xCenter = width / 2
66 | yCenter = (yMax - yMin) / 2
67 |
68 | # glyph I, cut thick stem
69 | if i == 0:
70 | intersections = intersect(glyph, yCenter, True)
71 |
72 | # glyph H, cut thin stem
73 | elif i == 1:
74 | intersections = intersect(glyph, xCenter, False)
75 |
76 | if len(intersections) > 1:
77 | (x1,y1), (x2,y2) = (intersections[0], intersections[-1])
78 |
79 | stemWidth = hypot(x2-x1, y2-y1)
80 | stems.append(round(stemWidth))
81 | else:
82 | stems.append(None)
83 |
84 | elif glyphName not in font:
85 | stems.append(None)
86 |
87 | if slantedSection == True and stems[0] is not None:
88 | stems[0] *= cos(radians(angle))
89 |
90 | return stems
91 |
92 |
93 | def getSlantAngle(font, returnDegrees=False):
94 | """Returns the probable slant/italic angle of a font measuring the slant of a capital I."""
95 |
96 | if 'I' in font:
97 | testGlyph = font['I']
98 | xMin, yMin, xMax, yMax = getGlyphBox(testGlyph)
99 | hCenter = (yMax - yMin) / 2
100 | delta = 10
101 | intersections = []
102 | glyph = freezeGlyph(testGlyph)
103 |
104 | for i in range(2):
105 | horizontal = hCenter + (i * delta)
106 | intersections.append(intersect(glyph, horizontal, True))
107 |
108 | if len(intersections) > 1:
109 | if len(intersections[0]) > 1 and len(intersections[1]) > 1:
110 | (x1,y1), (x2,y2) = (intersections[0][0], intersections[1][0])
111 | angle = atan2(x2-x1, y2-y1)
112 | if returnDegrees == False:
113 | return angle
114 | elif returnDegrees == True:
115 | return round(degrees(angle), 2)
116 | return 0
117 |
118 |
119 | def freezeGlyph(glyph):
120 | """Return a copy of a glyph, with components decomposed and all overlap removed."""
121 |
122 | toRFGlyph = RGlyph()
123 | toRFpen = toRFGlyph.getPen()
124 | # draw only the contours, decomposed components will be added later on
125 | for contour in glyph:
126 | contour.draw(toRFpen)
127 |
128 | if len(glyph.components):
129 | decomposedComponents = extractComposites(glyph)
130 | decomposedComponents.draw(toRFpen)
131 |
132 | singleContourGlyph = RGlyph()
133 | singleContourGlyph.width = glyph.width
134 | singleContourGlyph.name = glyph.name
135 | pointPen = singleContourGlyph.getPointPen()
136 |
137 | if len(toRFGlyph.contours) > 1:
138 |
139 | try:
140 | booleanGlyphs = []
141 |
142 | for c in toRFGlyph.contours:
143 | if len(c) > 1:
144 | b = BooleanGlyph()
145 | pen = b.getPen()
146 | c.draw(pen)
147 | booleanGlyphs.append(b)
148 |
149 | finalBooleanGlyph = reduce(lambda g1, g2: g1 | g2, booleanGlyphs)
150 | finalBooleanGlyph.drawPoints(pointPen)
151 |
152 | except:
153 | toRFGlyph.drawPoints(pointPen)
154 | else:
155 | toRFGlyph.drawPoints(pointPen)
156 |
157 | return singleContourGlyph
158 |
159 |
160 | def extractComposites(glyph):
161 | """Return a new glyph with outline copies of each composite from the source glyph."""
162 |
163 | decomposedComposites = RGlyph()
164 |
165 | if len(glyph.components):
166 | font = glyph.layer
167 |
168 | for comp in reversed(glyph.components):
169 |
170 | # obtain source data
171 | baseGlyphName = comp.baseGlyph
172 | baseGlyph = font[baseGlyphName]
173 | t = transform.Transform(*comp.transformation)
174 |
175 | # create a temporary glyph on which to draw the decomposed composite
176 | single_decomposedComposite = RGlyph()
177 | decompPen = single_decomposedComposite.getPen()
178 | baseGlyph.draw(decompPen)
179 | single_decomposedComposite.transformBy(tuple(t))
180 |
181 | # add single composite to the returned glyph
182 | decomposedComposites.appendGlyph(single_decomposedComposite)
183 |
184 | return decomposedComposites
185 |
186 |
187 | def intersect(glyph, where, isHorizontal):
188 | """
189 | Intersect a glyph with a horizontal or vertical line.
190 | Intersect each segment of a glyph using fontTools bezierTools.splitCubic and splitLine methods.
191 | """
192 | pen = CollectSegmentsPen(glyph.layer)
193 | glyph.draw(pen)
194 | nakedGlyph = pen.getSegments()
195 | glyphIntersections = []
196 |
197 | for i, contour in enumerate(nakedGlyph):
198 |
199 | for segment in contour:
200 |
201 | length = len(segment)
202 |
203 | if length == 2:
204 | pt1, pt2 = segment
205 | returnedSegments = splitLine(pt1, pt2, where, int(isHorizontal))
206 | elif length == 4:
207 | pt1, pt2, pt3, pt4 = segment
208 | returnedSegments = bezierTools.splitCubic(pt1, pt2, pt3, pt4, where, int(isHorizontal))
209 |
210 | if len(returnedSegments) > 1:
211 | intersectionPoints = findDuplicatePoints(returnedSegments)
212 | if len(intersectionPoints):
213 | box = calcBounds(segment)
214 | intersectionPoints = [point for point in intersectionPoints if arrayTools.pointInRect(point, box)]
215 | glyphIntersections.extend(intersectionPoints)
216 |
217 | return glyphIntersections
218 |
219 |
220 | def calcBounds(points):
221 | """
222 | Return rectangular bounds of a list of points.
223 | Similar to fontTools’ calcBounds only with rounding added,
224 | rounding is required for the test in intersect() to work.
225 | """
226 | xMin, xMax, yMin, yMax = None, None, None, None
227 | for (x, y) in points:
228 | for xRef in [xMin, xMax]:
229 | if xRef is None: xMin, xMax = x, x
230 | for yRef in [yMin, yMax]:
231 | if yRef is None: yMin, yMax = y, y
232 | if x > xMax: xMax = x
233 | if x < xMin: xMin = x
234 | if y > yMax: yMax = y
235 | if y < yMin: yMin = y
236 | box = [round(value, 4) for value in [xMin, yMin, xMax, yMax]]
237 | return tuple(box)
238 |
239 |
240 | def findDuplicatePoints(segments):
241 | counter = {}
242 | for seg in segments:
243 | for (x, y) in seg:
244 | p = round(x, 4), round(y, 4)
245 | if p in counter:
246 | counter[p] += 1
247 | elif not p in counter:
248 | counter[p] = 1
249 | return [key for key in counter if counter[key] > 1]
250 |
251 |
252 | def getGlyphBox(glyph):
253 | pen = BoundsPen(glyph.layer)
254 | glyph.draw(pen)
255 | return pen.bounds
256 |
257 |
258 | # had to fetch that splitLine method from Robofont’s version of fontTools
259 | # fontTools 2.4’s version was buggy.
260 |
261 | def splitLine(pt1, pt2, where, isHorizontal):
262 | """Split the line between pt1 and pt2 at position 'where', which
263 | is an x coordinate if isHorizontal is False, a y coordinate if
264 | isHorizontal is True. Return a list of two line segments if the
265 | line was successfully split, or a list containing the original
266 | line.
267 |
268 | >>> printSegments(splitLine((0, 0), (100, 100), 50, True))
269 | ((0, 0), (50.0, 50.0))
270 | ((50.0, 50.0), (100, 100))
271 | >>> printSegments(splitLine((0, 0), (100, 100), 100, True))
272 | ((0, 0), (100, 100))
273 | >>> printSegments(splitLine((0, 0), (100, 100), 0, True))
274 | ((0, 0), (0.0, 0.0))
275 | ((0.0, 0.0), (100, 100))
276 | >>> printSegments(splitLine((0, 0), (100, 100), 0, False))
277 | ((0, 0), (0.0, 0.0))
278 | ((0.0, 0.0), (100, 100))
279 | """
280 | pt1x, pt1y = pt1
281 | pt2x, pt2y = pt2
282 |
283 | ax = (pt2x - pt1x)
284 | ay = (pt2y - pt1y)
285 |
286 | bx = pt1x
287 | by = pt1y
288 |
289 | a = (ax, ay)[isHorizontal]
290 |
291 | if a == 0:
292 | return [(pt1, pt2)]
293 |
294 | t = float(where - (bx, by)[isHorizontal]) / a
295 | if 0 <= t < 1:
296 | midPt = ax * t + bx, ay * t + by
297 | return [(pt1, midPt), (midPt, pt2)]
298 | else:
299 | return [(pt1, pt2)]
300 |
301 |
302 |
303 |
304 | if __name__ == '__main__':
305 |
306 | import os
307 | import unittest
308 | from defcon import Font
309 |
310 | class FontUtilsTests(unittest.TestCase):
311 |
312 | def setUp(self):
313 | libFolder = os.path.dirname(os.path.dirname((os.path.dirname(os.path.abspath(__file__)))))
314 | singleFontPath = u'testFonts/isotropic-anisotropic/regular-mid-contrast.ufo'
315 | fontPath = os.path.join(libFolder, singleFontPath)
316 | self.font = Font(fontPath)
317 |
318 | def test_intersect_horizontal(self):
319 | glyph = self.font['I']
320 | yCenter = self.font.info.capHeight / 2
321 | intersections = intersect(glyph, yCenter, True)
322 | self.assertEqual(intersections, [(234.0, 375.0), (134.0, 375.0)])
323 |
324 | def test_intersect_vertical(self):
325 | glyph = self.font['H']
326 | xCenter = glyph.width / 2
327 | intersections = intersect(glyph, xCenter, False)
328 | self.assertEqual(intersections, [(426.5, 356.0), (426.5, 396.0)])
329 |
330 | def test_intersect_vertical_with_overlap_removed(self):
331 | glyph = freezeGlyph(self.font['H'])
332 | xCenter = glyph.width / 2
333 | intersections = intersect(glyph, xCenter, False)
334 | self.assertEqual(intersections, [(426.5, 356.0), (426.5, 396.0)])
335 |
336 | def test_getRefStems(self):
337 | stems = getRefStems(self.font)
338 |
339 | unittest.main()
340 |
--------------------------------------------------------------------------------
/source/lib/MutatorScale/lib/testFonts/isotropic-anisotropic/bold-mid-contrast.ufo/lib.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | com.typemytype.robofont.compileSettings.autohint
6 |
7 | com.typemytype.robofont.compileSettings.checkOutlines
8 |
9 | com.typemytype.robofont.compileSettings.decompose
10 |
11 | com.typemytype.robofont.compileSettings.generateFormat
12 | 0
13 | com.typemytype.robofont.compileSettings.releaseMode
14 |
15 | com.typemytype.robofont.italicSlantOffset
16 | 0
17 | com.typemytype.robofont.layerOrder
18 |
19 |
20 | com.typemytype.robofont.segmentType
21 | curve
22 | com.typemytype.robofont.shouldAddPointsInSplineConversion
23 | 0
24 | com.typemytype.robofont.sort
25 |
26 |
27 | ascending
28 |
29 | space
30 | exclam
31 | quotedbl
32 | numbersign
33 | dollar
34 | percent
35 | ampersand
36 | parenleft
37 | parenright
38 | asterisk
39 | plus
40 | comma
41 | hyphen
42 | period
43 | slash
44 | zero
45 | one
46 | two
47 | three
48 | four
49 | five
50 | six
51 | seven
52 | eight
53 | nine
54 | colon
55 | semicolon
56 | less
57 | equal
58 | greater
59 | question
60 | at
61 | A
62 | B
63 | C
64 | D
65 | E
66 | F
67 | G
68 | H
69 | I
70 | J
71 | K
72 | L
73 | M
74 | N
75 | O
76 | P
77 | Q
78 | R
79 | S
80 | T
81 | U
82 | V
83 | W
84 | X
85 | Y
86 | Z
87 | bracketleft
88 | backslash
89 | bracketright
90 | asciicircum
91 | underscore
92 | grave
93 | a
94 | b
95 | c
96 | d
97 | e
98 | f
99 | g
100 | h
101 | i
102 | j
103 | k
104 | l
105 | m
106 | n
107 | o
108 | p
109 | q
110 | r
111 | s
112 | t
113 | u
114 | v
115 | w
116 | x
117 | y
118 | z
119 | braceleft
120 | bar
121 | braceright
122 | asciitilde
123 | exclamdown
124 | cent
125 | sterling
126 | currency
127 | yen
128 | brokenbar
129 | section
130 | dieresis
131 | copyright
132 | ordfeminine
133 | guillemotleft
134 | logicalnot
135 | registered
136 | macron
137 | degree
138 | plusminus
139 | twosuperior
140 | threesuperior
141 | acute
142 | mu
143 | paragraph
144 | periodcentered
145 | cedilla
146 | onesuperior
147 | ordmasculine
148 | guillemotright
149 | onequarter
150 | onehalf
151 | threequarters
152 | questiondown
153 | Agrave
154 | Aacute
155 | Acircumflex
156 | Atilde
157 | Adieresis
158 | Aring
159 | AE
160 | Ccedilla
161 | Egrave
162 | Eacute
163 | Ecircumflex
164 | Edieresis
165 | Igrave
166 | Iacute
167 | Icircumflex
168 | Idieresis
169 | Eth
170 | Ntilde
171 | Ograve
172 | Oacute
173 | Ocircumflex
174 | Otilde
175 | Odieresis
176 | multiply
177 | Oslash
178 | Ugrave
179 | Uacute
180 | Ucircumflex
181 | Udieresis
182 | Yacute
183 | Thorn
184 | germandbls
185 | agrave
186 | aacute
187 | acircumflex
188 | atilde
189 | adieresis
190 | aring
191 | ae
192 | ccedilla
193 | egrave
194 | eacute
195 | ecircumflex
196 | edieresis
197 | igrave
198 | iacute
199 | icircumflex
200 | idieresis
201 | eth
202 | ntilde
203 | ograve
204 | oacute
205 | ocircumflex
206 | otilde
207 | odieresis
208 | divide
209 | oslash
210 | ugrave
211 | uacute
212 | ucircumflex
213 | udieresis
214 | yacute
215 | thorn
216 | ydieresis
217 | dotlessi
218 | circumflex
219 | caron
220 | breve
221 | dotaccent
222 | ring
223 | ogonek
224 | tilde
225 | hungarumlaut
226 | quoteleft
227 | quoteright
228 | minus
229 |
230 | type
231 | glyphList
232 |
233 |
234 | public.glyphOrder
235 |
236 | space
237 | exclam
238 | quotedbl
239 | numbersign
240 | dollar
241 | percent
242 | ampersand
243 | parenleft
244 | parenright
245 | asterisk
246 | plus
247 | comma
248 | hyphen
249 | period
250 | slash
251 | zero
252 | one
253 | two
254 | three
255 | four
256 | five
257 | six
258 | seven
259 | eight
260 | nine
261 | colon
262 | semicolon
263 | less
264 | equal
265 | greater
266 | question
267 | at
268 | A
269 | B
270 | C
271 | D
272 | E
273 | F
274 | G
275 | H
276 | I
277 | J
278 | K
279 | L
280 | M
281 | N
282 | O
283 | P
284 | Q
285 | R
286 | S
287 | T
288 | U
289 | V
290 | W
291 | X
292 | Y
293 | Z
294 | bracketleft
295 | backslash
296 | bracketright
297 | asciicircum
298 | underscore
299 | grave
300 | a
301 | b
302 | c
303 | d
304 | e
305 | f
306 | g
307 | h
308 | i
309 | j
310 | k
311 | l
312 | m
313 | n
314 | o
315 | p
316 | q
317 | r
318 | s
319 | t
320 | u
321 | v
322 | w
323 | x
324 | y
325 | z
326 | braceleft
327 | bar
328 | braceright
329 | asciitilde
330 | exclamdown
331 | cent
332 | sterling
333 | currency
334 | yen
335 | brokenbar
336 | section
337 | dieresis
338 | copyright
339 | ordfeminine
340 | guillemotleft
341 | logicalnot
342 | registered
343 | macron
344 | degree
345 | plusminus
346 | twosuperior
347 | threesuperior
348 | acute
349 | mu
350 | paragraph
351 | periodcentered
352 | cedilla
353 | onesuperior
354 | ordmasculine
355 | guillemotright
356 | onequarter
357 | onehalf
358 | threequarters
359 | questiondown
360 | Agrave
361 | Aacute
362 | Acircumflex
363 | Atilde
364 | Adieresis
365 | Aring
366 | AE
367 | Ccedilla
368 | Egrave
369 | Eacute
370 | Ecircumflex
371 | Edieresis
372 | Igrave
373 | Iacute
374 | Icircumflex
375 | Idieresis
376 | Eth
377 | Ntilde
378 | Ograve
379 | Oacute
380 | Ocircumflex
381 | Otilde
382 | Odieresis
383 | multiply
384 | Oslash
385 | Ugrave
386 | Uacute
387 | Ucircumflex
388 | Udieresis
389 | Yacute
390 | Thorn
391 | germandbls
392 | agrave
393 | aacute
394 | acircumflex
395 | atilde
396 | adieresis
397 | aring
398 | ae
399 | ccedilla
400 | egrave
401 | eacute
402 | ecircumflex
403 | edieresis
404 | igrave
405 | iacute
406 | icircumflex
407 | idieresis
408 | eth
409 | ntilde
410 | ograve
411 | oacute
412 | ocircumflex
413 | otilde
414 | odieresis
415 | divide
416 | oslash
417 | ugrave
418 | uacute
419 | ucircumflex
420 | udieresis
421 | yacute
422 | thorn
423 | ydieresis
424 | dotlessi
425 | circumflex
426 | caron
427 | breve
428 | dotaccent
429 | ring
430 | ogonek
431 | tilde
432 | hungarumlaut
433 | quoteleft
434 | quoteright
435 | minus
436 |
437 |
438 |
439 |
--------------------------------------------------------------------------------
/source/lib/MutatorScale/lib/testFonts/isotropic-anisotropic/regular-mid-contrast.ufo/lib.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | com.typemytype.robofont.compileSettings.autohint
6 |
7 | com.typemytype.robofont.compileSettings.checkOutlines
8 |
9 | com.typemytype.robofont.compileSettings.decompose
10 |
11 | com.typemytype.robofont.compileSettings.generateFormat
12 | 0
13 | com.typemytype.robofont.compileSettings.releaseMode
14 |
15 | com.typemytype.robofont.italicSlantOffset
16 | 0
17 | com.typemytype.robofont.layerOrder
18 |
19 |
20 | com.typemytype.robofont.segmentType
21 | curve
22 | com.typemytype.robofont.shouldAddPointsInSplineConversion
23 | 0
24 | com.typemytype.robofont.sort
25 |
26 |
27 | ascending
28 |
29 | space
30 | exclam
31 | quotedbl
32 | numbersign
33 | dollar
34 | percent
35 | ampersand
36 | parenleft
37 | parenright
38 | asterisk
39 | plus
40 | comma
41 | hyphen
42 | period
43 | slash
44 | zero
45 | one
46 | two
47 | three
48 | four
49 | five
50 | six
51 | seven
52 | eight
53 | nine
54 | colon
55 | semicolon
56 | less
57 | equal
58 | greater
59 | question
60 | at
61 | A
62 | B
63 | C
64 | D
65 | E
66 | F
67 | G
68 | H
69 | I
70 | J
71 | K
72 | L
73 | M
74 | N
75 | O
76 | P
77 | Q
78 | R
79 | S
80 | T
81 | U
82 | V
83 | W
84 | X
85 | Y
86 | Z
87 | bracketleft
88 | backslash
89 | bracketright
90 | asciicircum
91 | underscore
92 | grave
93 | a
94 | b
95 | c
96 | d
97 | e
98 | f
99 | g
100 | h
101 | i
102 | j
103 | k
104 | l
105 | m
106 | n
107 | o
108 | p
109 | q
110 | r
111 | s
112 | t
113 | u
114 | v
115 | w
116 | x
117 | y
118 | z
119 | braceleft
120 | bar
121 | braceright
122 | asciitilde
123 | exclamdown
124 | cent
125 | sterling
126 | currency
127 | yen
128 | brokenbar
129 | section
130 | dieresis
131 | copyright
132 | ordfeminine
133 | guillemotleft
134 | logicalnot
135 | registered
136 | macron
137 | degree
138 | plusminus
139 | twosuperior
140 | threesuperior
141 | acute
142 | mu
143 | paragraph
144 | periodcentered
145 | cedilla
146 | onesuperior
147 | ordmasculine
148 | guillemotright
149 | onequarter
150 | onehalf
151 | threequarters
152 | questiondown
153 | Agrave
154 | Aacute
155 | Acircumflex
156 | Atilde
157 | Adieresis
158 | Aring
159 | AE
160 | Ccedilla
161 | Egrave
162 | Eacute
163 | Ecircumflex
164 | Edieresis
165 | Igrave
166 | Iacute
167 | Icircumflex
168 | Idieresis
169 | Eth
170 | Ntilde
171 | Ograve
172 | Oacute
173 | Ocircumflex
174 | Otilde
175 | Odieresis
176 | multiply
177 | Oslash
178 | Ugrave
179 | Uacute
180 | Ucircumflex
181 | Udieresis
182 | Yacute
183 | Thorn
184 | germandbls
185 | agrave
186 | aacute
187 | acircumflex
188 | atilde
189 | adieresis
190 | aring
191 | ae
192 | ccedilla
193 | egrave
194 | eacute
195 | ecircumflex
196 | edieresis
197 | igrave
198 | iacute
199 | icircumflex
200 | idieresis
201 | eth
202 | ntilde
203 | ograve
204 | oacute
205 | ocircumflex
206 | otilde
207 | odieresis
208 | divide
209 | oslash
210 | ugrave
211 | uacute
212 | ucircumflex
213 | udieresis
214 | yacute
215 | thorn
216 | ydieresis
217 | dotlessi
218 | circumflex
219 | caron
220 | breve
221 | dotaccent
222 | ring
223 | ogonek
224 | tilde
225 | hungarumlaut
226 | quoteleft
227 | quoteright
228 | minus
229 |
230 | type
231 | glyphList
232 |
233 |
234 | public.glyphOrder
235 |
236 | space
237 | exclam
238 | quotedbl
239 | numbersign
240 | dollar
241 | percent
242 | ampersand
243 | parenleft
244 | parenright
245 | asterisk
246 | plus
247 | comma
248 | hyphen
249 | period
250 | slash
251 | zero
252 | one
253 | two
254 | three
255 | four
256 | five
257 | six
258 | seven
259 | eight
260 | nine
261 | colon
262 | semicolon
263 | less
264 | equal
265 | greater
266 | question
267 | at
268 | A
269 | B
270 | C
271 | D
272 | E
273 | F
274 | G
275 | H
276 | I
277 | J
278 | K
279 | L
280 | M
281 | N
282 | O
283 | P
284 | Q
285 | R
286 | S
287 | T
288 | U
289 | V
290 | W
291 | X
292 | Y
293 | Z
294 | bracketleft
295 | backslash
296 | bracketright
297 | asciicircum
298 | underscore
299 | grave
300 | a
301 | b
302 | c
303 | d
304 | e
305 | f
306 | g
307 | h
308 | i
309 | j
310 | k
311 | l
312 | m
313 | n
314 | o
315 | p
316 | q
317 | r
318 | s
319 | t
320 | u
321 | v
322 | w
323 | x
324 | y
325 | z
326 | braceleft
327 | bar
328 | braceright
329 | asciitilde
330 | exclamdown
331 | cent
332 | sterling
333 | currency
334 | yen
335 | brokenbar
336 | section
337 | dieresis
338 | copyright
339 | ordfeminine
340 | guillemotleft
341 | logicalnot
342 | registered
343 | macron
344 | degree
345 | plusminus
346 | twosuperior
347 | threesuperior
348 | acute
349 | mu
350 | paragraph
351 | periodcentered
352 | cedilla
353 | onesuperior
354 | ordmasculine
355 | guillemotright
356 | onequarter
357 | onehalf
358 | threequarters
359 | questiondown
360 | Agrave
361 | Aacute
362 | Acircumflex
363 | Atilde
364 | Adieresis
365 | Aring
366 | AE
367 | Ccedilla
368 | Egrave
369 | Eacute
370 | Ecircumflex
371 | Edieresis
372 | Igrave
373 | Iacute
374 | Icircumflex
375 | Idieresis
376 | Eth
377 | Ntilde
378 | Ograve
379 | Oacute
380 | Ocircumflex
381 | Otilde
382 | Odieresis
383 | multiply
384 | Oslash
385 | Ugrave
386 | Uacute
387 | Ucircumflex
388 | Udieresis
389 | Yacute
390 | Thorn
391 | germandbls
392 | agrave
393 | aacute
394 | acircumflex
395 | atilde
396 | adieresis
397 | aring
398 | ae
399 | ccedilla
400 | egrave
401 | eacute
402 | ecircumflex
403 | edieresis
404 | igrave
405 | iacute
406 | icircumflex
407 | idieresis
408 | eth
409 | ntilde
410 | ograve
411 | oacute
412 | ocircumflex
413 | otilde
414 | odieresis
415 | divide
416 | oslash
417 | ugrave
418 | uacute
419 | ucircumflex
420 | udieresis
421 | yacute
422 | thorn
423 | ydieresis
424 | dotlessi
425 | circumflex
426 | caron
427 | breve
428 | dotaccent
429 | ring
430 | ogonek
431 | tilde
432 | hungarumlaut
433 | quoteleft
434 | quoteright
435 | minus
436 |
437 |
438 |
439 |
--------------------------------------------------------------------------------
/source/lib/MutatorScale/lib/testFonts/two-axes/bold-high-contrast.ufo/lib.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | com.typemytype.robofont.background.layerStrokeColor
6 |
7 | 0.0
8 | 0.8
9 | 0.2
10 | 0.7
11 |
12 | com.typemytype.robofont.compileSettings.autohint
13 |
14 | com.typemytype.robofont.compileSettings.checkOutlines
15 |
16 | com.typemytype.robofont.compileSettings.decompose
17 |
18 | com.typemytype.robofont.compileSettings.generateFormat
19 | 0
20 | com.typemytype.robofont.compileSettings.releaseMode
21 |
22 | com.typemytype.robofont.italicSlantOffset
23 | 0
24 | com.typemytype.robofont.layerOrder
25 |
26 | background
27 |
28 | com.typemytype.robofont.segmentType
29 | curve
30 | com.typemytype.robofont.shouldAddPointsInSplineConversion
31 | 0
32 | com.typemytype.robofont.sort
33 |
34 |
35 | ascending
36 |
37 | space
38 | exclam
39 | quotedbl
40 | numbersign
41 | dollar
42 | percent
43 | ampersand
44 | parenleft
45 | parenright
46 | asterisk
47 | plus
48 | comma
49 | hyphen
50 | period
51 | slash
52 | zero
53 | one
54 | two
55 | three
56 | four
57 | five
58 | six
59 | seven
60 | eight
61 | nine
62 | colon
63 | semicolon
64 | less
65 | equal
66 | greater
67 | question
68 | at
69 | A
70 | B
71 | C
72 | D
73 | E
74 | F
75 | G
76 | H
77 | I
78 | J
79 | K
80 | L
81 | M
82 | N
83 | O
84 | P
85 | Q
86 | R
87 | S
88 | T
89 | U
90 | V
91 | W
92 | X
93 | Y
94 | Z
95 | bracketleft
96 | backslash
97 | bracketright
98 | asciicircum
99 | underscore
100 | grave
101 | a
102 | b
103 | c
104 | d
105 | e
106 | f
107 | g
108 | h
109 | i
110 | j
111 | k
112 | l
113 | m
114 | n
115 | o
116 | p
117 | q
118 | r
119 | s
120 | t
121 | u
122 | v
123 | w
124 | x
125 | y
126 | z
127 | braceleft
128 | bar
129 | braceright
130 | asciitilde
131 | exclamdown
132 | cent
133 | sterling
134 | currency
135 | yen
136 | brokenbar
137 | section
138 | dieresis
139 | copyright
140 | ordfeminine
141 | guillemotleft
142 | logicalnot
143 | registered
144 | macron
145 | degree
146 | plusminus
147 | twosuperior
148 | threesuperior
149 | acute
150 | mu
151 | paragraph
152 | periodcentered
153 | cedilla
154 | onesuperior
155 | ordmasculine
156 | guillemotright
157 | onequarter
158 | onehalf
159 | threequarters
160 | questiondown
161 | Agrave
162 | Aacute
163 | Acircumflex
164 | Atilde
165 | Adieresis
166 | Aring
167 | AE
168 | Ccedilla
169 | Egrave
170 | Eacute
171 | Ecircumflex
172 | Edieresis
173 | Igrave
174 | Iacute
175 | Icircumflex
176 | Idieresis
177 | Eth
178 | Ntilde
179 | Ograve
180 | Oacute
181 | Ocircumflex
182 | Otilde
183 | Odieresis
184 | multiply
185 | Oslash
186 | Ugrave
187 | Uacute
188 | Ucircumflex
189 | Udieresis
190 | Yacute
191 | Thorn
192 | germandbls
193 | agrave
194 | aacute
195 | acircumflex
196 | atilde
197 | adieresis
198 | aring
199 | ae
200 | ccedilla
201 | egrave
202 | eacute
203 | ecircumflex
204 | edieresis
205 | igrave
206 | iacute
207 | icircumflex
208 | idieresis
209 | eth
210 | ntilde
211 | ograve
212 | oacute
213 | ocircumflex
214 | otilde
215 | odieresis
216 | divide
217 | oslash
218 | ugrave
219 | uacute
220 | ucircumflex
221 | udieresis
222 | yacute
223 | thorn
224 | ydieresis
225 | dotlessi
226 | circumflex
227 | caron
228 | breve
229 | dotaccent
230 | ring
231 | ogonek
232 | tilde
233 | hungarumlaut
234 | quoteleft
235 | quoteright
236 | minus
237 |
238 | type
239 | glyphList
240 |
241 |
242 | public.glyphOrder
243 |
244 | space
245 | exclam
246 | quotedbl
247 | numbersign
248 | dollar
249 | percent
250 | ampersand
251 | parenleft
252 | parenright
253 | asterisk
254 | plus
255 | comma
256 | hyphen
257 | period
258 | slash
259 | zero
260 | one
261 | two
262 | three
263 | four
264 | five
265 | six
266 | seven
267 | eight
268 | nine
269 | colon
270 | semicolon
271 | less
272 | equal
273 | greater
274 | question
275 | at
276 | A
277 | B
278 | C
279 | D
280 | E
281 | F
282 | G
283 | H
284 | I
285 | J
286 | K
287 | L
288 | M
289 | N
290 | O
291 | P
292 | Q
293 | R
294 | S
295 | T
296 | U
297 | V
298 | W
299 | X
300 | Y
301 | Z
302 | bracketleft
303 | backslash
304 | bracketright
305 | asciicircum
306 | underscore
307 | grave
308 | a
309 | b
310 | c
311 | d
312 | e
313 | f
314 | g
315 | h
316 | i
317 | j
318 | k
319 | l
320 | m
321 | n
322 | o
323 | p
324 | q
325 | r
326 | s
327 | t
328 | u
329 | v
330 | w
331 | x
332 | y
333 | z
334 | braceleft
335 | bar
336 | braceright
337 | asciitilde
338 | exclamdown
339 | cent
340 | sterling
341 | currency
342 | yen
343 | brokenbar
344 | section
345 | dieresis
346 | copyright
347 | ordfeminine
348 | guillemotleft
349 | logicalnot
350 | registered
351 | macron
352 | degree
353 | plusminus
354 | twosuperior
355 | threesuperior
356 | acute
357 | mu
358 | paragraph
359 | periodcentered
360 | cedilla
361 | onesuperior
362 | ordmasculine
363 | guillemotright
364 | onequarter
365 | onehalf
366 | threequarters
367 | questiondown
368 | Agrave
369 | Aacute
370 | Acircumflex
371 | Atilde
372 | Adieresis
373 | Aring
374 | AE
375 | Ccedilla
376 | Egrave
377 | Eacute
378 | Ecircumflex
379 | Edieresis
380 | Igrave
381 | Iacute
382 | Icircumflex
383 | Idieresis
384 | Eth
385 | Ntilde
386 | Ograve
387 | Oacute
388 | Ocircumflex
389 | Otilde
390 | Odieresis
391 | multiply
392 | Oslash
393 | Ugrave
394 | Uacute
395 | Ucircumflex
396 | Udieresis
397 | Yacute
398 | Thorn
399 | germandbls
400 | agrave
401 | aacute
402 | acircumflex
403 | atilde
404 | adieresis
405 | aring
406 | ae
407 | ccedilla
408 | egrave
409 | eacute
410 | ecircumflex
411 | edieresis
412 | igrave
413 | iacute
414 | icircumflex
415 | idieresis
416 | eth
417 | ntilde
418 | ograve
419 | oacute
420 | ocircumflex
421 | otilde
422 | odieresis
423 | divide
424 | oslash
425 | ugrave
426 | uacute
427 | ucircumflex
428 | udieresis
429 | yacute
430 | thorn
431 | ydieresis
432 | dotlessi
433 | circumflex
434 | caron
435 | breve
436 | dotaccent
437 | ring
438 | ogonek
439 | tilde
440 | hungarumlaut
441 | quoteleft
442 | quoteright
443 | minus
444 |
445 |
446 |
447 |
--------------------------------------------------------------------------------
/source/lib/MutatorScale/lib/testFonts/two-axes/bold-low-contrast.ufo/lib.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | com.typemytype.robofont.background.layerStrokeColor
6 |
7 | 0.0
8 | 0.8
9 | 0.2
10 | 0.7
11 |
12 | com.typemytype.robofont.compileSettings.autohint
13 |
14 | com.typemytype.robofont.compileSettings.checkOutlines
15 |
16 | com.typemytype.robofont.compileSettings.decompose
17 |
18 | com.typemytype.robofont.compileSettings.generateFormat
19 | 0
20 | com.typemytype.robofont.compileSettings.releaseMode
21 |
22 | com.typemytype.robofont.italicSlantOffset
23 | 0
24 | com.typemytype.robofont.layerOrder
25 |
26 | background
27 |
28 | com.typemytype.robofont.segmentType
29 | curve
30 | com.typemytype.robofont.shouldAddPointsInSplineConversion
31 | 0
32 | com.typemytype.robofont.sort
33 |
34 |
35 | ascending
36 |
37 | space
38 | exclam
39 | quotedbl
40 | numbersign
41 | dollar
42 | percent
43 | ampersand
44 | parenleft
45 | parenright
46 | asterisk
47 | plus
48 | comma
49 | hyphen
50 | period
51 | slash
52 | zero
53 | one
54 | two
55 | three
56 | four
57 | five
58 | six
59 | seven
60 | eight
61 | nine
62 | colon
63 | semicolon
64 | less
65 | equal
66 | greater
67 | question
68 | at
69 | A
70 | B
71 | C
72 | D
73 | E
74 | F
75 | G
76 | H
77 | I
78 | J
79 | K
80 | L
81 | M
82 | N
83 | O
84 | P
85 | Q
86 | R
87 | S
88 | T
89 | U
90 | V
91 | W
92 | X
93 | Y
94 | Z
95 | bracketleft
96 | backslash
97 | bracketright
98 | asciicircum
99 | underscore
100 | grave
101 | a
102 | b
103 | c
104 | d
105 | e
106 | f
107 | g
108 | h
109 | i
110 | j
111 | k
112 | l
113 | m
114 | n
115 | o
116 | p
117 | q
118 | r
119 | s
120 | t
121 | u
122 | v
123 | w
124 | x
125 | y
126 | z
127 | braceleft
128 | bar
129 | braceright
130 | asciitilde
131 | exclamdown
132 | cent
133 | sterling
134 | currency
135 | yen
136 | brokenbar
137 | section
138 | dieresis
139 | copyright
140 | ordfeminine
141 | guillemotleft
142 | logicalnot
143 | registered
144 | macron
145 | degree
146 | plusminus
147 | twosuperior
148 | threesuperior
149 | acute
150 | mu
151 | paragraph
152 | periodcentered
153 | cedilla
154 | onesuperior
155 | ordmasculine
156 | guillemotright
157 | onequarter
158 | onehalf
159 | threequarters
160 | questiondown
161 | Agrave
162 | Aacute
163 | Acircumflex
164 | Atilde
165 | Adieresis
166 | Aring
167 | AE
168 | Ccedilla
169 | Egrave
170 | Eacute
171 | Ecircumflex
172 | Edieresis
173 | Igrave
174 | Iacute
175 | Icircumflex
176 | Idieresis
177 | Eth
178 | Ntilde
179 | Ograve
180 | Oacute
181 | Ocircumflex
182 | Otilde
183 | Odieresis
184 | multiply
185 | Oslash
186 | Ugrave
187 | Uacute
188 | Ucircumflex
189 | Udieresis
190 | Yacute
191 | Thorn
192 | germandbls
193 | agrave
194 | aacute
195 | acircumflex
196 | atilde
197 | adieresis
198 | aring
199 | ae
200 | ccedilla
201 | egrave
202 | eacute
203 | ecircumflex
204 | edieresis
205 | igrave
206 | iacute
207 | icircumflex
208 | idieresis
209 | eth
210 | ntilde
211 | ograve
212 | oacute
213 | ocircumflex
214 | otilde
215 | odieresis
216 | divide
217 | oslash
218 | ugrave
219 | uacute
220 | ucircumflex
221 | udieresis
222 | yacute
223 | thorn
224 | ydieresis
225 | dotlessi
226 | circumflex
227 | caron
228 | breve
229 | dotaccent
230 | ring
231 | ogonek
232 | tilde
233 | hungarumlaut
234 | quoteleft
235 | quoteright
236 | minus
237 |
238 | type
239 | glyphList
240 |
241 |
242 | public.glyphOrder
243 |
244 | space
245 | exclam
246 | quotedbl
247 | numbersign
248 | dollar
249 | percent
250 | ampersand
251 | parenleft
252 | parenright
253 | asterisk
254 | plus
255 | comma
256 | hyphen
257 | period
258 | slash
259 | zero
260 | one
261 | two
262 | three
263 | four
264 | five
265 | six
266 | seven
267 | eight
268 | nine
269 | colon
270 | semicolon
271 | less
272 | equal
273 | greater
274 | question
275 | at
276 | A
277 | B
278 | C
279 | D
280 | E
281 | F
282 | G
283 | H
284 | I
285 | J
286 | K
287 | L
288 | M
289 | N
290 | O
291 | P
292 | Q
293 | R
294 | S
295 | T
296 | U
297 | V
298 | W
299 | X
300 | Y
301 | Z
302 | bracketleft
303 | backslash
304 | bracketright
305 | asciicircum
306 | underscore
307 | grave
308 | a
309 | b
310 | c
311 | d
312 | e
313 | f
314 | g
315 | h
316 | i
317 | j
318 | k
319 | l
320 | m
321 | n
322 | o
323 | p
324 | q
325 | r
326 | s
327 | t
328 | u
329 | v
330 | w
331 | x
332 | y
333 | z
334 | braceleft
335 | bar
336 | braceright
337 | asciitilde
338 | exclamdown
339 | cent
340 | sterling
341 | currency
342 | yen
343 | brokenbar
344 | section
345 | dieresis
346 | copyright
347 | ordfeminine
348 | guillemotleft
349 | logicalnot
350 | registered
351 | macron
352 | degree
353 | plusminus
354 | twosuperior
355 | threesuperior
356 | acute
357 | mu
358 | paragraph
359 | periodcentered
360 | cedilla
361 | onesuperior
362 | ordmasculine
363 | guillemotright
364 | onequarter
365 | onehalf
366 | threequarters
367 | questiondown
368 | Agrave
369 | Aacute
370 | Acircumflex
371 | Atilde
372 | Adieresis
373 | Aring
374 | AE
375 | Ccedilla
376 | Egrave
377 | Eacute
378 | Ecircumflex
379 | Edieresis
380 | Igrave
381 | Iacute
382 | Icircumflex
383 | Idieresis
384 | Eth
385 | Ntilde
386 | Ograve
387 | Oacute
388 | Ocircumflex
389 | Otilde
390 | Odieresis
391 | multiply
392 | Oslash
393 | Ugrave
394 | Uacute
395 | Ucircumflex
396 | Udieresis
397 | Yacute
398 | Thorn
399 | germandbls
400 | agrave
401 | aacute
402 | acircumflex
403 | atilde
404 | adieresis
405 | aring
406 | ae
407 | ccedilla
408 | egrave
409 | eacute
410 | ecircumflex
411 | edieresis
412 | igrave
413 | iacute
414 | icircumflex
415 | idieresis
416 | eth
417 | ntilde
418 | ograve
419 | oacute
420 | ocircumflex
421 | otilde
422 | odieresis
423 | divide
424 | oslash
425 | ugrave
426 | uacute
427 | ucircumflex
428 | udieresis
429 | yacute
430 | thorn
431 | ydieresis
432 | dotlessi
433 | circumflex
434 | caron
435 | breve
436 | dotaccent
437 | ring
438 | ogonek
439 | tilde
440 | hungarumlaut
441 | quoteleft
442 | quoteright
443 | minus
444 |
445 |
446 |
447 |
--------------------------------------------------------------------------------
/source/lib/MutatorScale/lib/testFonts/two-axes/bold-italic-low-contrast.ufo/lib.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | com.typemytype.robofont.background.layerStrokeColor
6 |
7 | 0.0
8 | 0.8
9 | 0.2
10 | 0.7
11 |
12 | com.typemytype.robofont.compileSettings.autohint
13 |
14 | com.typemytype.robofont.compileSettings.checkOutlines
15 |
16 | com.typemytype.robofont.compileSettings.decompose
17 |
18 | com.typemytype.robofont.compileSettings.generateFormat
19 | 0
20 | com.typemytype.robofont.compileSettings.releaseMode
21 |
22 | com.typemytype.robofont.italicSlantOffset
23 | 0
24 | com.typemytype.robofont.layerOrder
25 |
26 | background
27 |
28 | com.typemytype.robofont.segmentType
29 | curve
30 | com.typemytype.robofont.shouldAddPointsInSplineConversion
31 | 0
32 | com.typemytype.robofont.sort
33 |
34 |
35 | ascending
36 |
37 | space
38 | exclam
39 | quotedbl
40 | numbersign
41 | dollar
42 | percent
43 | ampersand
44 | parenleft
45 | parenright
46 | asterisk
47 | plus
48 | comma
49 | hyphen
50 | period
51 | slash
52 | zero
53 | one
54 | two
55 | three
56 | four
57 | five
58 | six
59 | seven
60 | eight
61 | nine
62 | colon
63 | semicolon
64 | less
65 | equal
66 | greater
67 | question
68 | at
69 | A
70 | B
71 | C
72 | D
73 | E
74 | F
75 | G
76 | H
77 | I
78 | J
79 | K
80 | L
81 | M
82 | N
83 | O
84 | P
85 | Q
86 | R
87 | S
88 | T
89 | U
90 | V
91 | W
92 | X
93 | Y
94 | Z
95 | bracketleft
96 | backslash
97 | bracketright
98 | asciicircum
99 | underscore
100 | grave
101 | a
102 | b
103 | c
104 | d
105 | e
106 | f
107 | g
108 | h
109 | i
110 | j
111 | k
112 | l
113 | m
114 | n
115 | o
116 | p
117 | q
118 | r
119 | s
120 | t
121 | u
122 | v
123 | w
124 | x
125 | y
126 | z
127 | braceleft
128 | bar
129 | braceright
130 | asciitilde
131 | exclamdown
132 | cent
133 | sterling
134 | currency
135 | yen
136 | brokenbar
137 | section
138 | dieresis
139 | copyright
140 | ordfeminine
141 | guillemotleft
142 | logicalnot
143 | registered
144 | macron
145 | degree
146 | plusminus
147 | twosuperior
148 | threesuperior
149 | acute
150 | mu
151 | paragraph
152 | periodcentered
153 | cedilla
154 | onesuperior
155 | ordmasculine
156 | guillemotright
157 | onequarter
158 | onehalf
159 | threequarters
160 | questiondown
161 | Agrave
162 | Aacute
163 | Acircumflex
164 | Atilde
165 | Adieresis
166 | Aring
167 | AE
168 | Ccedilla
169 | Egrave
170 | Eacute
171 | Ecircumflex
172 | Edieresis
173 | Igrave
174 | Iacute
175 | Icircumflex
176 | Idieresis
177 | Eth
178 | Ntilde
179 | Ograve
180 | Oacute
181 | Ocircumflex
182 | Otilde
183 | Odieresis
184 | multiply
185 | Oslash
186 | Ugrave
187 | Uacute
188 | Ucircumflex
189 | Udieresis
190 | Yacute
191 | Thorn
192 | germandbls
193 | agrave
194 | aacute
195 | acircumflex
196 | atilde
197 | adieresis
198 | aring
199 | ae
200 | ccedilla
201 | egrave
202 | eacute
203 | ecircumflex
204 | edieresis
205 | igrave
206 | iacute
207 | icircumflex
208 | idieresis
209 | eth
210 | ntilde
211 | ograve
212 | oacute
213 | ocircumflex
214 | otilde
215 | odieresis
216 | divide
217 | oslash
218 | ugrave
219 | uacute
220 | ucircumflex
221 | udieresis
222 | yacute
223 | thorn
224 | ydieresis
225 | dotlessi
226 | circumflex
227 | caron
228 | breve
229 | dotaccent
230 | ring
231 | ogonek
232 | tilde
233 | hungarumlaut
234 | quoteleft
235 | quoteright
236 | minus
237 |
238 | type
239 | glyphList
240 |
241 |
242 | public.glyphOrder
243 |
244 | space
245 | exclam
246 | quotedbl
247 | numbersign
248 | dollar
249 | percent
250 | ampersand
251 | parenleft
252 | parenright
253 | asterisk
254 | plus
255 | comma
256 | hyphen
257 | period
258 | slash
259 | zero
260 | one
261 | two
262 | three
263 | four
264 | five
265 | six
266 | seven
267 | eight
268 | nine
269 | colon
270 | semicolon
271 | less
272 | equal
273 | greater
274 | question
275 | at
276 | A
277 | B
278 | C
279 | D
280 | E
281 | F
282 | G
283 | H
284 | I
285 | J
286 | K
287 | L
288 | M
289 | N
290 | O
291 | P
292 | Q
293 | R
294 | S
295 | T
296 | U
297 | V
298 | W
299 | X
300 | Y
301 | Z
302 | bracketleft
303 | backslash
304 | bracketright
305 | asciicircum
306 | underscore
307 | grave
308 | a
309 | b
310 | c
311 | d
312 | e
313 | f
314 | g
315 | h
316 | i
317 | j
318 | k
319 | l
320 | m
321 | n
322 | o
323 | p
324 | q
325 | r
326 | s
327 | t
328 | u
329 | v
330 | w
331 | x
332 | y
333 | z
334 | braceleft
335 | bar
336 | braceright
337 | asciitilde
338 | exclamdown
339 | cent
340 | sterling
341 | currency
342 | yen
343 | brokenbar
344 | section
345 | dieresis
346 | copyright
347 | ordfeminine
348 | guillemotleft
349 | logicalnot
350 | registered
351 | macron
352 | degree
353 | plusminus
354 | twosuperior
355 | threesuperior
356 | acute
357 | mu
358 | paragraph
359 | periodcentered
360 | cedilla
361 | onesuperior
362 | ordmasculine
363 | guillemotright
364 | onequarter
365 | onehalf
366 | threequarters
367 | questiondown
368 | Agrave
369 | Aacute
370 | Acircumflex
371 | Atilde
372 | Adieresis
373 | Aring
374 | AE
375 | Ccedilla
376 | Egrave
377 | Eacute
378 | Ecircumflex
379 | Edieresis
380 | Igrave
381 | Iacute
382 | Icircumflex
383 | Idieresis
384 | Eth
385 | Ntilde
386 | Ograve
387 | Oacute
388 | Ocircumflex
389 | Otilde
390 | Odieresis
391 | multiply
392 | Oslash
393 | Ugrave
394 | Uacute
395 | Ucircumflex
396 | Udieresis
397 | Yacute
398 | Thorn
399 | germandbls
400 | agrave
401 | aacute
402 | acircumflex
403 | atilde
404 | adieresis
405 | aring
406 | ae
407 | ccedilla
408 | egrave
409 | eacute
410 | ecircumflex
411 | edieresis
412 | igrave
413 | iacute
414 | icircumflex
415 | idieresis
416 | eth
417 | ntilde
418 | ograve
419 | oacute
420 | ocircumflex
421 | otilde
422 | odieresis
423 | divide
424 | oslash
425 | ugrave
426 | uacute
427 | ucircumflex
428 | udieresis
429 | yacute
430 | thorn
431 | ydieresis
432 | dotlessi
433 | circumflex
434 | caron
435 | breve
436 | dotaccent
437 | ring
438 | ogonek
439 | tilde
440 | hungarumlaut
441 | quoteleft
442 | quoteright
443 | minus
444 |
445 |
446 |
447 |
--------------------------------------------------------------------------------