Refactored (made standalone repo)

This commit is contained in:
twardoch 2020-04-10 13:08:59 +02:00
parent 36042cc3de
commit 20f70c7b27
38 changed files with 139 additions and 1431 deletions

View File

@ -1,5 +1,4 @@
Apache License
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
@ -179,7 +178,7 @@
APPENDIX: How to apply the Apache License to your work.
To apply the Apache License to your work, attach the following
boilerplate notice, with the fields enclosed by brackets "[]"
boilerplate notice, with the fields enclosed by brackets "{}"
replaced with your own identifying information. (Don't include
the brackets!) The text should be enclosed in the appropriate
comment syntax for the file format. We also recommend that a
@ -187,7 +186,7 @@
same "printed page" as the copyright notice for easier
identification within third-party archives.
Copyright [yyyy] [name of copyright owner]
Copyright {yyyy} {name of copyright owner}
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
@ -200,3 +199,4 @@
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.

139
README.md
View File

@ -1,5 +1,136 @@
# fonttools-utils
This repository holds various font-related tools and utilities written by Adam Twardoch.
OpenType Feature Freezer
=======================
* **[MacOSXSystemFontReplacer](./mac-os-x-system-font-replacer)** — a tool to replace your system UI fonts of Mac OS X 10.10 Yosemite with any fonts of your choice
* **[pyftfeatfreeze](./pyftfeatfreeze)** — a tool to “freeze” some OpenType features into a font, so small caps, oldstyle numerals or localized forms become available in apps that dont support OpenType Layout features (such as many office apps)
With **pyftfeatfreeze**, you can “freeze” some OpenType features into a font.
These features are then “on by default”, so characters previously accessible through OpenType features only (such as smallcaps, oldstyle numerals or localized forms) will now be accessible even in apps that dont support OpenType features, such as LibreOffice, OpenOffice, or in apps that dont support a particular feature, such as Microsoft Office in case of smallcaps.
*Note: This tool actually remaps the `cmap` table of the font by applying the specified `GSUB` features. It will not work for substitutions where neither glyph has any `cmap` entries. Only single and alternate substitutions are supported.*
Installation
-----------
This tool requires Python 3.6 or above to be installed first. Get it from https://www.python.org or your package manager.
**XXX: Upload this package to Pypi**
### Recommended
We recommend using [pipx](https://pypi.org/project/pipx/) to install Python command line tools. Pipx tucks them away neatly on your computer and gives you an easy way to add, update and remove Python tools on all platforms, without leaving a mess in your Python installation.
```
pipx install opentype-feature-freezer
```
### Other methods
Install it with `pip`, as any other Python package.
```
# This is best done inside a virtual environment, so you don't pollute
# your Python installation and need no special privileges to install anything.
pip install opentype-feature-freezer
```
Examples
--------
Lets say you have the font *CharisSIL-R.ttf* (with the menu name “Charis SIL”), and this font includes true smallcaps accessible via the OpenType Layout features `c2sc` (for uppercase) and `smcp` (for lowercase). Lets say that youd like to make a second font where the **true smallcaps** are available by default. Just run:
```
pyftfeatfreeze -f 'c2sc,smcp' -S -U SC -R 'Charis SIL/Charix,CharisSIL/Charix' CharisSIL-R.ttf CharixSC-R.ttf
```
Youll get a new font *CharisSIL-R.ttf* (with the menu name “Charix SC”). This font will have smallcaps instead of the lowercase and uppercase letters, available in all apps.
Since the “Charis SIL” font is licensed under the OFL, and uses the Reserved Font Names “Charis” and “SIL”, Ive specified the `-R` option to replace the name strings `Charis SIL` and `CharisSIL` with `Charix`. This way, the modified font is compliant with the OFL and I can distribute it.
The following example remaps the font so that the **Bulgarian localized forms** are available by default in all apps (the suffix “BG” will be added to the menu name):
```
pyftfeatfreeze -f 'locl' -s 'cyrl' -l 'BGR ' -S -U BG SomeFont.ttf SomeFontBG.ttf
```
*Note: To remap features from multiple scripts or languagesystems, run the tool multiple times (taking the previous runs output as input). Use the `-S` option only on the final run.*
The following replaces the string `Lato` by `Otal` in all internal font names (in the `name` and `CFF ` tables), without doing any “feature freezing”. This can be used to quickly change some internal font names:
```
pyftfeatfreeze -R 'Lato/Otal' Lato-Regular.ttf Otal-Regular.ttf
```
Command-line syntax
-------------------
```
usage: pyftfeatfreeze [-h] [-f FEATURES] [-s SCRIPT] [-l LANG] [-z] [-S]
[-U USESUFFIX] [-R REPLACENAMES] [-i] [-r] [-n] [-v]
[-V]
inpath [outpath]
With pyftfeatfreeze you can "freeze" some OpenType features into a font. These
features are then "on by default", even in apps that don't support OpenType
features. Internally, the tool remaps the "cmap" table of the font by applying
the specified GSUB features. Only single and alternate substitutions are
supported.
positional arguments:
inpath input .otf or .ttf font file
outpath output .otf or .ttf font file (optional)
optional arguments:
-h, --help show this help message and exit
options to control feature freezing:
-f FEATURES, --features FEATURES
comma-separated list of OpenType feature tags, e.g.
'smcp,c2sc,onum'
-s SCRIPT, --script SCRIPT
OpenType script tag, e.g. 'cyrl' (default: 'latn')
-l LANG, --lang LANG OpenType language tag, e.g. 'SRB ' (optional)
-z, --zapnames zap glyphnames from the font ('post' table version 3,
.ttf only)
options to control font renaming:
-S, --suffix add a suffix to the font family name (by default, the
suffix will be constructed from the OpenType feature
tags)
-U USESUFFIX, --usesuffix USESUFFIX
use a custom suffix when -S is provided
-R REPLACENAMES, --replacenames REPLACENAMES
search for strings in the font naming tables and
replace them, format is
'search1/replace1,search2/replace2,...'
-i, --info update font version string
reporting options:
-r, --report report languages, scripts and features in font
-n, --names output names of remapped glyphs during processing
-v, --verbose print additional information during processing
-V, --version show program's version number and exit
Examples:
pyftfeatfreeze -f 'c2sc,smcp' -S -U SC OpenSans.ttf OpenSansSC.ttf
pyftfeatfreeze -R 'Lato/Otal' Lato-Regular.ttf Otal-Regular.ttf
```
*Tip: the `-n` option outputs a space-separated list of “frozen” glyphs. If you redirect it to a file, you can use this list as input for `pyftsubset` to create a small font that only includes the “frozen” glyphs.*
Software License and Disclaimer
-------------------------------
This tool is licensed “as is” under the [Apache License, Version 2.0](http://www.apache.org/licenses/LICENSE-2.0). By using the tool, you accept all conditions of the license, including Disclaimer of Warranty and Limitation of Liability. **If you use this tool, please consult if your fonts EULA allows modifications. If the font is licensed under the OFL, please use the `-R` option to change the Reserved Font Name to something else.**
Requirements
------------
This tool is written for Python 3.6+ and requires [fontTools/TTX](https://github.com/behdad/fonttools/).
Credits
-------
* Code by [Adam Twardoch](./AUTHORS)
* Homepage: [https://github.com/twardoch/fonttools-utils/](https://github.com/twardoch/fonttools-utils/)

View File

@ -1,10 +0,0 @@
# This is the official list of authors of software
# in this repository for copyright purposes.
# This file is distinct from the CONTRIBUTORS files.
# See the latter for an explanation.
# Names should be added to this file as:
# Name or Organization <email address>
# The email address is not required for organizations.
Adam Twardoch <adam@twardoch.com>

View File

@ -1,8 +0,0 @@
# This is the official list of people who can contribute
# (and typically have contributed) code to this repository.
# The AUTHORS file lists the copyright holders; this file
# lists people.
# Names should be added to this file like so:
# Name <email address>
Adam Twardoch <adam@twardoch.com>

View File

@ -1,202 +0,0 @@
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS
APPENDIX: How to apply the Apache License to your work.
To apply the Apache License to your work, attach the following
boilerplate notice, with the fields enclosed by brackets "{}"
replaced with your own identifying information. (Don't include
the brackets!) The text should be enclosed in the appropriate
comment syntax for the file format. We also recommend that a
file or class name and description of purpose be included on the
same "printed page" as the copyright notice for easier
identification within third-party archives.
Copyright {yyyy} {name of copyright owner}
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.

View File

@ -1,196 +0,0 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
VERSION = "1.1"
"""MacOSXSystemFontReplacer.py
Version %(version)s
Copyright (c) 2015 by Adam Twardoch <adam@twardoch.com>
Licensed under the Apache 2 license.
""" % {"version": VERSION}
import argparse
import os
import os.path
import fontTools.ttLib
import subprocess
parser = argparse.ArgumentParser()
parser.description = """With %(prog)s v""" + VERSION + """,
you can replace your system UI fonts of Mac OS X 10.10 Yosemite with any fonts
of your choice. You can supply any fonts to the tool as long as they have filenames in a format that
the tool expects. Please run %(prog)s -H for the exact file names you should provide. The tool is 'safe' i.e.
it does not modify the original system UI fonts. Instead, it writes patched versions of the fonts you
provide into the System library folder, but you can easily uninstall those later manually or using the tool itself.
"""
parser.add_argument("-i", "--input-folder",
help="path to folder with your input font files, default is %(default)s",
default=os.getcwd()
)
parser.add_argument("-s", "--font-size",
help="scale the relative font size in %%, default is %(default)s, use a higher value such as 105 to optically increase your patched UI fonts",
type=int,
default=100
)
parser.add_argument("-o", "--output-folder",
help="custom path to folder where your patched fonts will be installed, default is %(default)s and you should run the tool as: sudo %(prog)s",
default="/Library/Fonts/"
)
parser.add_argument("-H", "--help-more",
help="print the file names that the tool expects to find in the -i INPUT_FOLDER",
action="store_true",
default=False
)
parser.add_argument("-u", "--uninstall",
help="uninstall previously patched fonts from system folder or the -o OUTPUT_FOLDER",
action="store_true",
default=False
)
parser.add_argument("-c", "--no-reset-caches",
help="do not reset OS X font caches (useful if you are testing and using a custom -o OUTPUT_FOLDER)",
action="store_true",
default=True
)
parser.add_argument("-t", "--system-ttc",
help="custom path to %(default)s (which may be different from current default in future versions of OS X)",
default="/System/Library/Fonts/HelveticaNeueDeskInterface.ttc"
)
args = parser.parse_args()
def patchFont(ttcPath, fontNumber, inFolder, outFolder, help, fontScale, uninstall):
success = False
try:
ttxIn = fontTools.ttLib.TTFont(ttcPath, fontNumber=fontNumber)
except fontTools.ttLib.TTLibError:
ttxIn = None
if ttxIn:
fontName = ""
nameRecord = ttxIn["name"].getName(4, 1, 0, 0)
if nameRecord:
fontName = nameRecord.string
else:
nameRecord = ttxIn["name"].getName(4, 0, 3, 0)
if nameRecord:
fontName = unicode(
nameRecord.string, 'utf-16-be').encode('utf-8')
if help:
print('"%s.otf"' % fontName)
elif uninstall:
fontPathOut = os.path.join(outFolder, "%s.otf" % (fontName))
if os.path.exists:
try:
os.remove(fontPathOut)
print("Uninstalled: %s" % (fontPathOut))
success = True
except:
print(
"Cannot uninstall: %s (try running tool with 'sudo'!)" % (fontPathOut))
else:
fontPath = os.path.join(inFolder, "%s.otf" % (fontName))
if os.path.exists(fontPath):
ttxOut = fontTools.ttLib.TTFont(fontPath)
scaleFactor = (
float(ttxOut["head"].unitsPerEm)/ttxIn["head"].unitsPerEm)/fontScale
ttxOut[
"OS/2"].sTypoAscender = int(ttxIn["OS/2"].sTypoAscender * scaleFactor + 0.5)
ttxOut[
"OS/2"].sTypoDescender = int(ttxIn["OS/2"].sTypoDescender * scaleFactor + 0.5)
ttxOut[
"OS/2"].sTypoLineGap = int(ttxIn["OS/2"].sTypoLineGap * scaleFactor + 0.5)
ttxOut[
"OS/2"].usWinAscent = int(ttxIn["OS/2"].usWinAscent * scaleFactor + 0.5)
ttxOut[
"OS/2"].usWinDescent = int(ttxIn["OS/2"].usWinDescent * scaleFactor + 0.5)
ttxOut["hhea"].ascent = int(
ttxIn["hhea"].ascent * scaleFactor + 0.5)
ttxOut["hhea"].descent = int(
ttxIn["hhea"].descent * scaleFactor + 0.5)
ttxOut["hhea"].lineGap = int(
ttxIn["hhea"].lineGap * scaleFactor + 0.5)
ttxOut["name"] = ttxIn["name"]
ttxOut["head"].unitsPerEm = int(
ttxOut["head"].unitsPerEm / fontScale + 0.5)
if "CFF " in ttxOut:
cff = ttxOut["CFF "].cff
cffd = cff[cff.fontNames[0]].rawDict
cffd["FontMatrix"][0] = cffd["FontMatrix"][0] * fontScale
cffd["FontMatrix"][3] = cffd["FontMatrix"][3] * fontScale
psName = None
psNameRecord = ttxIn["name"].getName(6, 1, 0, 0)
if psNameRecord:
psName = psNameRecord.string
else:
psNameRecord = ttxIn["name"].getName(6, 0, 3, 0)
if psNameRecord:
psName = unicode(
psNameRecord.string, 'utf-16-be').encode('utf-8')
if psName:
cff.fontNames[0] = psName
fullName = None
fullNameRecord = ttxIn["name"].getName(4, 1, 0, 0)
if fullNameRecord:
fullName = fullNameRecord.string
else:
fullNameRecord = ttxIn["name"].getName(4, 0, 3, 0)
if fullNameRecord:
fullName = unicode(
fullNameRecord.string, 'utf-16-be').encode('utf-8')
if fullName:
cffd["FullName"] = fullName
famName = None
famNameRecord = ttxIn["name"].getName(1, 1, 0, 0)
if famNameRecord:
famName = famNameRecord.string
else:
famNameRecord = ttxIn["name"].getName(1, 0, 3, 0)
if famNameRecord:
famName = unicode(
famNameRecord.string, 'utf-16-be').encode('utf-8')
if famName:
cffd["FamilyName"] = famName
fontPathOut = os.path.join(outFolder, "%s.otf" % (fontName))
try:
ttxOut.save(fontPathOut)
print('Saved patched: "%s"' % (fontPathOut))
success = True
except:
print(
"Cannot save: %s (try running tool with 'sudo'!)" % (fontPathOut))
else:
print('Not found: "%s"' % (fontPath))
return (ttxIn, success)
if args.help_more:
print("This tool expects your font files with the following file names to be present in\n%s :" % (
args.input_folder))
fontNumber = 0
patchedFonts = 0
while True:
(opened, patched) = patchFont(ttcPath=args.system_ttc, fontNumber=fontNumber, inFolder=args.input_folder,
outFolder=args.output_folder, help=args.help_more, fontScale=float(args.font_size)/100, uninstall=args.uninstall)
if opened:
fontNumber += 1
else:
break
if patched:
patchedFonts += 1
if args.help_more:
print("The tool will match each of your fonts to one of the internal Mac OS X UI fonts\n(stored in %s)\nusing the filename.\nThen it will try to patch your fonts and install them in %s.\nAfter logging out and back in, you should see your new UI fonts." % (
args.system_ttc, args.output_folder))
else:
if args.uninstall:
print("Uninstalled %d fonts" % (patchedFonts))
else:
print("Finished patching %d fonts" % (patchedFonts))
if not args.no_reset_caches:
subprocess.call(["sudo", "atsutil", "databases", "-remove"])
print(
"Mac OS X font caches have been reset. Please log out of Mac OS X and log in again.")

View File

@ -1,115 +0,0 @@
MacOSXSystemFontReplacer
========================
With **[MacOSXSystemFontReplacer](http://bit.ly/MacOSXSystemFontReplacer)**, you can replace your system UI fonts of
Mac OS X 10.10 Yosemite with any fonts of your choice.
You can supply any fonts to the tool as long as they have filenames in
a format that the tool expects.
The tool is “safe” i.e. it does not modify the original system UI fonts. Instead, it writes patched versions of the fonts you provide into the System library folder, but you can easily uninstall those later manually or using the tool itself. Also, since it uses the fontTools library, it only does minimal modifications to your fonts, retaining all essential information. The fonts that you want patched can be in ```.ttf``` or ```.otf``` format, but you need to rename them and use the ```.otf``` extension.
**If you use this tool, please consult if your fonts EULA allows modifications. Since this tool copies a small bit of the OS X system font into the patched fonts, you should not redistribute the patched fonts.**
![Example: Work Sans](example-work-sans.png?raw=true "Example: I have used the tool to replace the default UI system font with Work Sans")
*This example shows how the tool was used to replace the default UI system fonts of Mac OS X 10.10 with the open-source [Work Sans](http://weiweihuanghuang.github.io/Work-Sans/) font family. The ```-s 105``` option was used to visually increase the font sizes by 5%.*
Installation and basic usage
----------------------------
This is a command-line tool written in Python.
1. Download and install¹ [fontTools/TTX](https://github.com/behdad/fonttools/)
2. Download **[MacOSXSystemFontReplacer.py](./MacOSXSystemFontReplacer.py?raw=true)** and save it in a folder
3. Place your fonts in the same folder
3. Rename your fonts to a scheme that the tool expects (see section “Preparing your fonts” below)
4. Run Terminal.app and navigate to that folder using ```cd```
5. Run ```sudo python ./MacOSXSystemFontReplacer.py```
6. Enter your OS X Administrator password
7. Log out of Mac OS X and log in again
¹To install **fontTools/TTX**: download the [fonttools-master.zip](https://github.com/behdad/fonttools/archive/master.zip?raw=true) archive, unzip it, open Terminal.app and navigate to the unzipped folder using ```cd```. Then just type ```sudo python setup.py install``` and enter your Administrator password.
Advanced usage
--------------
There are more options to the tool:
```
MacOSXSystemFontReplacer.py [-h] [-i INPUT_FOLDER] [-s FONT_SIZE]
[-o OUTPUT_FOLDER] [-H] [-u] [-c]
[-t SYSTEM_TTC]
-h, --help show this help message and exit
-i INPUT_FOLDER, --input-folder INPUT_FOLDER
path to folder with your input font files, default is
/Users/adam/Developer/vcs/github/twardoch/fonttools-
utils/mac-os-x-system-font-replacer
-s FONT_SIZE, --font-size FONT_SIZE
scale the relative font size in %, default is 100, use
a higher value such as 105 to optically increase your
patched UI fonts
-o OUTPUT_FOLDER, --output-folder OUTPUT_FOLDER
custom path to folder where your patched fonts will be
installed, default is /Library/Fonts/ and you should
run the tool as: sudo MacOSXSystemFontReplacer.py
-H, --help-more print the file names that the tool expects to find in
the -i INPUT_FOLDER
-u, --uninstall uninstall previously patched fonts from the system folder
or the -o OUTPUT_FOLDER
-c, --no-reset-caches
do not reset OS X font caches (useful if you are
testing and using a custom -o OUTPUT_FOLDER)
-t SYSTEM_TTC, --system-ttc SYSTEM_TTC
custom path to
/System/Library/Fonts/HelveticaNeueDeskInterface.ttc
(which may be different from current default in future
versions of OS X)
```
Preparing your fonts
--------------------
If you wish to replace all system UI fonts of Mac OS X 10.10 Yosemite with your custom fonts, you need to **rename the font files exactly** so that each of your font files has one of file names given in the table below. The table also indicates the general usage of the font and the relationships in the design of the original system font family.
Filename | Usage | Design
---------| ------| ------
**System Font Regular.otf** | menus and other widgets | the main UI font
**System Font Bold.otf** | app menu and other emphasis | bolder version of Regular
**System Font Italic.otf** | emphasis | italic version of Regular
**System Font Bold Italic.otf** | | Bold Italic version of Regular
**System Font Medium P4.otf** | notification titles | slightly bolder than Regular
**System Font Medium Italic P4.otf** | emphasis of above | slightly bolder than Italic
**System Font UltraLight.otf** | largest headlines¹ | thinnest
**System Font Thin.otf** | mid-sized headlines² | slightly bolder than UltraLight
**System Font Light.otf** | yet smaller headlines³ | slightly bolder than Thin
**System Font Heavy.otf** | | bolder than Bold
¹e.g. in Calendar for month²e.g. in the headline of Notification Center³or as bold for the UltraLight e.g. in Calendar for year
You need to place the font files renamed according to the above scheme in a folder, and then you need to specify that folder using the ```-i``` command-line option. (If the tool is in the same folder as the fonts, you can omit that option). The tool will match each of your fonts to one of the default Mac OS X UI fonts using the filename.
Then it will try to patch your fonts and install them in ```/Library/Fonts/```. Then you **log out and back in**, and you should see your new UI fonts.
Notes
-----
Please use the file names exactly as provided, and **use the ```.otf``` extension** even if your fonts are actually ```.ttf```.
The most important fonts are *System Font Regular.otf* and *System Font Bold.otf*. You dont need to provide all fonts (then the default system font will still be used in some places).
If you find that after logging out and in again, the new UI fonts are visually too small, run the tool again, but this time, provide an ```-s``` command-line option with a percentage scaling. Usually a value such as ```-s 105``` will be good enough.
In Mac OS X 10.10 Yosemite, the default Mac OS X UI fonts are stored in ```/System/Library/Fonts/HelveticaNeueDeskInterface.ttc```. The tool allows you to point to a different ```.ttc``` font as default, so it should work even in newer OS X versions.
Software License and Disclaimer
-------------------------------
This tool is licensed “as is” under the [Apache License, Version 2.0](http://www.apache.org/licenses/LICENSE-2.0). By using the tool, you accept all conditions of the license, including Disclaimer of Warranty and Limitation of Liability.
Requirements
------------
This tool is written in Python 2.7 and requires the fontTools/TTX package from https://github.com/behdad/fonttools/
Credits
-------
* Code by [Adam Twardoch](./AUTHORS)
* Inspired by https://github.com/jenskutilek/FiraSystemFontReplacement and https://github.com/dtinth/YosemiteSystemFontPatcher
* Homepage: http://bit.ly/MacOSXSystemFontReplacer

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.1 MiB

View File

@ -1,34 +0,0 @@
[run]
# measure 'branch' coverage in addition to 'statement' coverage
# See: http://coverage.readthedocs.org/en/coverage-4.0.3/branch.html#branch
branch = True
parallel = True
# list of directories or packages to measure
source = opentype_feature_freezer
# these are treated as equivalent when combining data
[paths]
source =
opentype_feature_freezer
src/opentype_feature_freezer
.tox/*/Lib/python*/site-packages/opentype_feature_freezer
.tox/*/Lib/site-packages/opentype_feature_freezer
.tox/pypy*/site-packages/opentype_feature_freezer
[report]
# Regexes for lines to exclude from consideration
exclude_lines =
# keywords to use in inline comments to skip coverage
pragma: no cover
# don't complain if tests don't hit defensive assertion code
raise AssertionError
raise NotImplementedError
# don't complain if non-runnable code isn't run
if 0:
if __name__ == .__main__.:
# ignore source code that cant be found
ignore_errors = True

View File

@ -1,15 +0,0 @@
# http://editorconfig.org
root = true
[*]
indent_style = space
indent_size = 4
trim_trailing_whitespace = true
insert_final_newline = true
charset = utf-8
end_of_line = lf
[*.{yaml,yml}]
indent_style = space
indent_size = 2

View File

@ -1,2 +0,0 @@
# Normalize all text files to have LF line-ednings.
* text=auto

View File

@ -1,108 +0,0 @@
# Byte-compiled / optimized / DLL files
__pycache__/
*.py[cod]
*$py.class
# C extensions
*.so
# Distribution / packaging
.Python
env/
build/
develop-eggs/
dist/
downloads/
eggs/
.eggs/
parts/
sdist/
var/
wheels/
*.egg-info/
.installed.cfg
*.egg
# PyInstaller
# Usually these files are written by a python script from a template
# before PyInstaller builds the exe, so as to inject date/other infos into it.
*.manifest
*.spec
# Installer logs
pip-log.txt
pip-delete-this-directory.txt
# Unit test / coverage reports
htmlcov/
.tox/
.coverage
.coverage.*
.cache
nosetests.xml
coverage.xml
*.cover
.hypothesis/
.pytest_cache/
# Translations
*.mo
*.pot
# Django stuff:
*.log
local_settings.py
# Flask stuff:
instance/
.webassets-cache
# Scrapy stuff:
.scrapy
# Sphinx documentation
docs/_build/
# PyBuilder
target/
# Jupyter Notebook
.ipynb_checkpoints
# pyenv
.python-version
# celery beat schedule file
celerybeat-schedule
# SageMath parsed files
*.sage.py
# dotenv
.env
# virtualenv
.venv
venv/
ENV/
# Spyder project settings
.spyderproject
.spyproject
# Rope project settings
.ropeproject
# mkdocs documentation
/site
# mypy
.mypy_cache/
# VS Code
.vscode
.idea
# Fontlab
.vfb
.bak

View File

@ -1,14 +0,0 @@
[MESSAGES CONTROL]
# Disable the message, report, category or checker with the given id(s). You
# can either give multiple identifier separated by comma (,) or put this option
# multiple time (only on the command line, not in the configuration file where
# it should appear only once).
disable=
bad-continuation,
broad-except,
invalid-name,
line-too-long,
missing-docstring,
missing-function-docstring,
protected-access,

View File

@ -1,202 +0,0 @@
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS
APPENDIX: How to apply the Apache License to your work.
To apply the Apache License to your work, attach the following
boilerplate notice, with the fields enclosed by brackets "{}"
replaced with your own identifying information. (Don't include
the brackets!) The text should be enclosed in the appropriate
comment syntax for the file format. We also recommend that a
file or class name and description of purpose be included on the
same "printed page" as the copyright notice for easier
identification within third-party archives.
Copyright {yyyy} {name of copyright owner}
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.

View File

@ -1,136 +0,0 @@
OpenType Feature Freezer
=======================
With **pyftfeatfreeze**, you can “freeze” some OpenType features into a font.
These features are then “on by default”, so characters previously accessible through OpenType features only (such as smallcaps, oldstyle numerals or localized forms) will now be accessible even in apps that dont support OpenType features, such as LibreOffice, OpenOffice, or in apps that dont support a particular feature, such as Microsoft Office in case of smallcaps.
*Note: This tool actually remaps the `cmap` table of the font by applying the specified `GSUB` features. It will not work for substitutions where neither glyph has any `cmap` entries. Only single and alternate substitutions are supported.*
Installation
-----------
This tool requires Python 3.6 or above to be installed first. Get it from https://www.python.org or your package manager.
**XXX: Upload this package to Pypi**
### Recommended
We recommend using [pipx](https://pypi.org/project/pipx/) to install Python command line tools. Pipx tucks them away neatly on your computer and gives you an easy way to add, update and remove Python tools on all platforms, without leaving a mess in your Python installation.
```
pipx install opentype-feature-freezer
```
### Other methods
Install it with `pip`, as any other Python package.
```
# This is best done inside a virtual environment, so you don't pollute
# your Python installation and need no special privileges to install anything.
pip install opentype-feature-freezer
```
Examples
--------
Lets say you have the font *CharisSIL-R.ttf* (with the menu name “Charis SIL”), and this font includes true smallcaps accessible via the OpenType Layout features `c2sc` (for uppercase) and `smcp` (for lowercase). Lets say that youd like to make a second font where the **true smallcaps** are available by default. Just run:
```
pyftfeatfreeze -f 'c2sc,smcp' -S -U SC -R 'Charis SIL/Charix,CharisSIL/Charix' CharisSIL-R.ttf CharixSC-R.ttf
```
Youll get a new font *CharisSIL-R.ttf* (with the menu name “Charix SC”). This font will have smallcaps instead of the lowercase and uppercase letters, available in all apps.
Since the “Charis SIL” font is licensed under the OFL, and uses the Reserved Font Names “Charis” and “SIL”, Ive specified the `-R` option to replace the name strings `Charis SIL` and `CharisSIL` with `Charix`. This way, the modified font is compliant with the OFL and I can distribute it.
The following example remaps the font so that the **Bulgarian localized forms** are available by default in all apps (the suffix “BG” will be added to the menu name):
```
pyftfeatfreeze -f 'locl' -s 'cyrl' -l 'BGR ' -S -U BG SomeFont.ttf SomeFontBG.ttf
```
*Note: To remap features from multiple scripts or languagesystems, run the tool multiple times (taking the previous runs output as input). Use the `-S` option only on the final run.*
The following replaces the string `Lato` by `Otal` in all internal font names (in the `name` and `CFF ` tables), without doing any “feature freezing”. This can be used to quickly change some internal font names:
```
pyftfeatfreeze -R 'Lato/Otal' Lato-Regular.ttf Otal-Regular.ttf
```
Command-line syntax
-------------------
```
usage: pyftfeatfreeze [-h] [-f FEATURES] [-s SCRIPT] [-l LANG] [-z] [-S]
[-U USESUFFIX] [-R REPLACENAMES] [-i] [-r] [-n] [-v]
[-V]
inpath [outpath]
With pyftfeatfreeze you can "freeze" some OpenType features into a font. These
features are then "on by default", even in apps that don't support OpenType
features. Internally, the tool remaps the "cmap" table of the font by applying
the specified GSUB features. Only single and alternate substitutions are
supported.
positional arguments:
inpath input .otf or .ttf font file
outpath output .otf or .ttf font file (optional)
optional arguments:
-h, --help show this help message and exit
options to control feature freezing:
-f FEATURES, --features FEATURES
comma-separated list of OpenType feature tags, e.g.
'smcp,c2sc,onum'
-s SCRIPT, --script SCRIPT
OpenType script tag, e.g. 'cyrl' (default: 'latn')
-l LANG, --lang LANG OpenType language tag, e.g. 'SRB ' (optional)
-z, --zapnames zap glyphnames from the font ('post' table version 3,
.ttf only)
options to control font renaming:
-S, --suffix add a suffix to the font family name (by default, the
suffix will be constructed from the OpenType feature
tags)
-U USESUFFIX, --usesuffix USESUFFIX
use a custom suffix when -S is provided
-R REPLACENAMES, --replacenames REPLACENAMES
search for strings in the font naming tables and
replace them, format is
'search1/replace1,search2/replace2,...'
-i, --info update font version string
reporting options:
-r, --report report languages, scripts and features in font
-n, --names output names of remapped glyphs during processing
-v, --verbose print additional information during processing
-V, --version show program's version number and exit
Examples:
pyftfeatfreeze -f 'c2sc,smcp' -S -U SC OpenSans.ttf OpenSansSC.ttf
pyftfeatfreeze -R 'Lato/Otal' Lato-Regular.ttf Otal-Regular.ttf
```
*Tip: the `-n` option outputs a space-separated list of “frozen” glyphs. If you redirect it to a file, you can use this list as input for `pyftsubset` to create a small font that only includes the “frozen” glyphs.*
Software License and Disclaimer
-------------------------------
This tool is licensed “as is” under the [Apache License, Version 2.0](http://www.apache.org/licenses/LICENSE-2.0). By using the tool, you accept all conditions of the license, including Disclaimer of Warranty and Limitation of Liability. **If you use this tool, please consult if your fonts EULA allows modifications. If the font is licensed under the OFL, please use the `-R` option to change the Reserved Font Name to something else.**
Requirements
------------
This tool is written for Python 3.6+ and requires [fontTools/TTX](https://github.com/behdad/fonttools/).
Credits
-------
* Code by [Adam Twardoch](./AUTHORS)
* Homepage: [https://github.com/twardoch/fonttools-utils/](https://github.com/twardoch/fonttools-utils/)

View File

@ -1,10 +0,0 @@
# This is the official list of authors of software
# in this repository for copyright purposes.
# This file is distinct from the CONTRIBUTORS files.
# See the latter for an explanation.
# Names should be added to this file as:
# Name or Organization <email address>
# The email address is not required for organizations.
Adam Twardoch <adam@twardoch.com>

View File

@ -1,8 +0,0 @@
# This is the official list of people who can contribute
# (and typically have contributed) code to this repository.
# The AUTHORS file lists the copyright holders; this file
# lists people.
# Names should be added to this file like so:
# Name <email address>
Adam Twardoch <adam@twardoch.com>

View File

@ -1,202 +0,0 @@
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS
APPENDIX: How to apply the Apache License to your work.
To apply the Apache License to your work, attach the following
boilerplate notice, with the fields enclosed by brackets "{}"
replaced with your own identifying information. (Don't include
the brackets!) The text should be enclosed in the appropriate
comment syntax for the file format. We also recommend that a
file or class name and description of purpose be included on the
same "printed page" as the copyright notice for easier
identification within third-party archives.
Copyright {yyyy} {name of copyright owner}
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.

View File

@ -1,68 +0,0 @@
ttxjson
=======
**ttxjson** is a Python tool that converts an SFNT font (OTF, TTF)
into JSON, using the [`fontTools`](https://github.com/fonttools/fonttools/) and [`jsonpickle`](https://github.com/jsonpickle/jsonpickle) Python modules.
Installation on Mac OS X
------------------------
* Download and unzip https://github.com/twardoch/fonttools-utils/archive/master.zip
* Open Terminal and navigate to the folder where youve unzipped the archive.
* Type these lines one by one, enter the Administrator password after the first "sudo" line:
```
pip install --user git+https://github.com/fonttools/fonttools.git
pip install --user git+https://github.com/jsonpickle/jsonpickle.git
cd ttxjson
chmod gou+x ttxjson.py
sudo mkdir -p /usr/local/bin
sudo cp ttxjson.py /usr/local/bin
```
* Test if the tool is available in Terminal by typing `ttxjson.py -h`
Command-line syntax
-------------------
```
usage: ttxjson.py [-h] [-o OUTPUT] [-t TABLES] infontpath
ttxjson.py is a Python tool that converts an SFNT font (OTF, TTF) into JSON.
Homepage: https://github.com/twardoch/fonttools-utils/
positional arguments:
infontpath Input SFNT font file (.otf, .ttf)
optional arguments:
-h, --help show this help message and exit
-o OUTPUT, --output OUTPUT
Output JSON path, stdout if not given
-t TABLES, --tables TABLES
Comma-separated list of SFNT tables, e.g.
CFF,head,name
```
Python usage
------------
```python
import ttxjson
import fontTools.ttLib
font = fontTools.ttLib.TTFont(fontPath, lazy=False, ignoreDecompileErrors=True)
jsonString = ttxjson.ttxJson(font, tables=['head','name','CFF '])
print jsonString
import json
jsonDict = json.loads(jsonString)
upm = jsonDict[u'tables'][u'head'][u'unitsPerEm']
print upm
```
Software License and Disclaimer
-------------------------------
This tool is licensed “as is” under the [Apache License, Version 2.0](http://www.apache.org/licenses/LICENSE-2.0). By using the tool, you accept all conditions of the license, including Disclaimer of Warranty and Limitation of Liability. **If you use this tool, please consult if your fonts EULA allows modifications. If the font is licensed under the OFL, please use the `-R` option to change the Reserved Font Name to something else.**
Requirements
------------
This tool is written in Python 2.7 and requires [`fontTools`](https://github.com/fonttools/fonttools/) and [`jsonpickle`](https://github.com/jsonpickle/jsonpickle).
Credits
-------
* Code by [Adam Twardoch](./AUTHORS)
* Homepage: [https://github.com/twardoch/fonttools-utils/](https://github.com/twardoch/fonttools-utils/)

View File

@ -1,93 +0,0 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
from __future__ import print_function
VERSION = "1.00"
"""ttxjson.py
Version %(version)s
Copyright (c) 2016 by Adam Twardoch <adam@twardoch.com>
Licensed under the Apache 2 license.
""" % {"version": VERSION}
# fontTools gives access to internal SFNT font structures
# INSTALL
# pip install --user git+https://github.com/fonttools/fonttools.git
import fontTools.ttLib
def ttxJson(font, tables=None):
# jsonpickle is a module that converts a more complex Python
# data structure to a JSON string, and back
# https://jsonpickle.github.io/
# INSTALL
# pip install --user git+https://github.com/jsonpickle/jsonpickle.git
import jsonpickle
if not tables:
tables = set(font.keys())
# To create a jsonString Pythonvia jsonpickle, we need first to iterate through
# each font table to force decompilation from SFNT into Pythonic object structures.
# The tables which are not decompiled will be jsonpickled as base64 SFNT blocks.
# ** Is there a better method? **
templist = [font[tag] for tag in tables]
# We jsonpickle.encode the font into jsonString
jsonString = jsonpickle.encode(font)
return jsonString
def main():
import os.path
import sys
from argparse import ArgumentParser
# json is a built-in Python module that allows simple conversion
# between JSON strings and Python dicts
# https://docs.python.org/2/library/json.html
import json
parser = ArgumentParser()
parser.description = """
%(prog)s is a Python tool that converts an SFNT font (OTF, TTF) into JSON.
Homepage: https://github.com/twardoch/fonttools-utils/
"""
parser.add_argument('infontpath', help='Input SFNT font file (.otf, .ttf)')
parser.add_argument('-o', '--output', help='Output JSON path, stdout if not given')
parser.add_argument('-t', '--tables', help='Comma-separated list of SFNT tables, e.g. CFF,head,name')
args = vars(parser.parse_args())
# Get a font path and output JSON path
if args['infontpath']:
fontPath = args['infontpath']
if not os.path.exists(fontPath):
print("%s does not exist" % (fontPath), file=sys.stderr)
sys.exit(-2)
else:
parser.print_help()
sys.exit(0)
# Create fontTools font object
font = fontTools.ttLib.TTFont(fontPath, lazy=False, ignoreDecompileErrors=True)
# Get an optional list of comma-separated SFNT tables to decompile
# as in "CFF,name,fvar"
if args['tables']:
todotables = args['tables'].split(",")
tables = set([tag.ljust(4) for tag in todotables]) & set(font.keys())
else:
tables = set(font.keys())
# We get the JSON representation of the font
jsonString = ttxJson(font, tables)
# We load it into a Python dict via json.loads
jsonDict = json.loads(jsonString)
# We dump the Python dict into a jsonFormatted string
jsonFormatted = json.dumps(jsonDict, sort_keys=True, indent=2)
# We write the jsonFormatted string into jsonPath
if args['output']:
jsonFile = file(args['output'], "w")
else:
jsonFile = sys.stdout
print(jsonFormatted, file=jsonFile)
# Example using jsonDict:
# upm = jsonDict[u'tables'][u'head'][u'unitsPerEm']
if __name__ == "__main__":
main()