├── imgs
├── step1.png
└── step2.png
├── fonts
├── Zebrawood.otf
├── Zebrawood-Dots.otf
├── Zebrawood-Fill.otf
├── Zebrawood-Shadow.otf
└── test.html
├── tests
├── fixtures
│ ├── 1.ttf
│ ├── 12.ttf
│ ├── 13.ttf
│ ├── 14.ttf
│ ├── 2.ttf
│ ├── 23.ttf
│ ├── 24.ttf
│ ├── 3.ttf
│ ├── 34.ttf
│ ├── 4.ttf
│ ├── aA.ttf
│ ├── ab.ttf
│ ├── bc.ttf
│ ├── cd.ttf
│ ├── 1234.ttf
│ ├── blank_glyph.ttf
│ ├── no_glyf_table.ttf
│ ├── no_head_table.ttf
│ ├── b.svg
│ ├── Y.svg
│ ├── A.svg
│ └── Z.svg
├── dumpsvg_test.py
├── conftest.py
├── shared_utils_test.py
├── options_test.py
└── fonts2svg_test.py
├── pytest.ini
├── .gitignore
├── .coveragerc
├── setup.py
├── .github
└── workflows
│ ├── publish.yml
│ └── test.yml
├── LICENSE.md
├── README.md
└── lib
└── opentypesvg
├── utils.py
├── dumpsvg.py
├── addsvg.py
└── fonts2svg.py
/imgs/step1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/adobe-type-tools/opentype-svg/HEAD/imgs/step1.png
--------------------------------------------------------------------------------
/imgs/step2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/adobe-type-tools/opentype-svg/HEAD/imgs/step2.png
--------------------------------------------------------------------------------
/fonts/Zebrawood.otf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/adobe-type-tools/opentype-svg/HEAD/fonts/Zebrawood.otf
--------------------------------------------------------------------------------
/tests/fixtures/1.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/adobe-type-tools/opentype-svg/HEAD/tests/fixtures/1.ttf
--------------------------------------------------------------------------------
/tests/fixtures/12.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/adobe-type-tools/opentype-svg/HEAD/tests/fixtures/12.ttf
--------------------------------------------------------------------------------
/tests/fixtures/13.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/adobe-type-tools/opentype-svg/HEAD/tests/fixtures/13.ttf
--------------------------------------------------------------------------------
/tests/fixtures/14.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/adobe-type-tools/opentype-svg/HEAD/tests/fixtures/14.ttf
--------------------------------------------------------------------------------
/tests/fixtures/2.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/adobe-type-tools/opentype-svg/HEAD/tests/fixtures/2.ttf
--------------------------------------------------------------------------------
/tests/fixtures/23.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/adobe-type-tools/opentype-svg/HEAD/tests/fixtures/23.ttf
--------------------------------------------------------------------------------
/tests/fixtures/24.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/adobe-type-tools/opentype-svg/HEAD/tests/fixtures/24.ttf
--------------------------------------------------------------------------------
/tests/fixtures/3.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/adobe-type-tools/opentype-svg/HEAD/tests/fixtures/3.ttf
--------------------------------------------------------------------------------
/tests/fixtures/34.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/adobe-type-tools/opentype-svg/HEAD/tests/fixtures/34.ttf
--------------------------------------------------------------------------------
/tests/fixtures/4.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/adobe-type-tools/opentype-svg/HEAD/tests/fixtures/4.ttf
--------------------------------------------------------------------------------
/tests/fixtures/aA.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/adobe-type-tools/opentype-svg/HEAD/tests/fixtures/aA.ttf
--------------------------------------------------------------------------------
/tests/fixtures/ab.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/adobe-type-tools/opentype-svg/HEAD/tests/fixtures/ab.ttf
--------------------------------------------------------------------------------
/tests/fixtures/bc.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/adobe-type-tools/opentype-svg/HEAD/tests/fixtures/bc.ttf
--------------------------------------------------------------------------------
/tests/fixtures/cd.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/adobe-type-tools/opentype-svg/HEAD/tests/fixtures/cd.ttf
--------------------------------------------------------------------------------
/fonts/Zebrawood-Dots.otf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/adobe-type-tools/opentype-svg/HEAD/fonts/Zebrawood-Dots.otf
--------------------------------------------------------------------------------
/fonts/Zebrawood-Fill.otf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/adobe-type-tools/opentype-svg/HEAD/fonts/Zebrawood-Fill.otf
--------------------------------------------------------------------------------
/pytest.ini:
--------------------------------------------------------------------------------
1 | [pytest]
2 | testpaths = tests
3 | filterwarnings =
4 | ignore:The py23 module:DeprecationWarning
5 |
--------------------------------------------------------------------------------
/tests/fixtures/1234.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/adobe-type-tools/opentype-svg/HEAD/tests/fixtures/1234.ttf
--------------------------------------------------------------------------------
/fonts/Zebrawood-Shadow.otf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/adobe-type-tools/opentype-svg/HEAD/fonts/Zebrawood-Shadow.otf
--------------------------------------------------------------------------------
/tests/fixtures/blank_glyph.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/adobe-type-tools/opentype-svg/HEAD/tests/fixtures/blank_glyph.ttf
--------------------------------------------------------------------------------
/tests/fixtures/no_glyf_table.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/adobe-type-tools/opentype-svg/HEAD/tests/fixtures/no_glyf_table.ttf
--------------------------------------------------------------------------------
/tests/fixtures/no_head_table.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/adobe-type-tools/opentype-svg/HEAD/tests/fixtures/no_head_table.ttf
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | *.pyc
2 | *.egg-info
3 | build
4 | venv
5 | dist
6 | .eggs
7 | __version__.py
8 | .coverage
9 | htmlcov
10 | xtra
11 |
--------------------------------------------------------------------------------
/tests/dumpsvg_test.py:
--------------------------------------------------------------------------------
1 | # Copyright 2021 Adobe. All rights reserved.
2 |
3 | import pytest
4 |
5 | from opentypesvg.dumpsvg import main
6 |
7 |
8 | def test_font_without_svg_table(base_font_path, capsys):
9 | with pytest.raises(SystemExit):
10 | main([base_font_path])
11 | captured = capsys.readouterr()
12 | assert captured.err == "ERROR: The font does not have the SVG table.\n"
13 |
--------------------------------------------------------------------------------
/tests/fixtures/b.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/fonts/test.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | SVG font test
6 |
26 |
27 |
28 | AYZ
29 |
30 |
31 |
--------------------------------------------------------------------------------
/.coveragerc:
--------------------------------------------------------------------------------
1 | [run]
2 | # measure 'branch' coverage in addition to 'statement' coverage
3 | # See: http://coverage.readthedocs.io/en/coverage-4.5.1/branch.html
4 | branch = True
5 | parallel = True
6 |
7 | # list of directories or packages to measure
8 | source =
9 | opentypesvg
10 |
11 | omit =
12 | tests
13 | */__version__.py
14 |
15 | [report]
16 | # Regexes for lines to exclude from consideration
17 | exclude_lines =
18 | # keywords to use in inline comments to skip coverage
19 | pragma: no cover
20 |
21 | # don't complain if tests don't hit defensive assertion code
22 | # ...
23 |
24 | # don't complain if non-runnable code isn't run
25 | if __name__ == .__main__.:
26 |
27 | # ignore source code that can’t be found
28 | ignore_errors = True
29 |
--------------------------------------------------------------------------------
/tests/conftest.py:
--------------------------------------------------------------------------------
1 | # Copyright 2021 Adobe. All rights reserved.
2 |
3 | import os
4 | import pytest
5 |
6 |
7 | @pytest.fixture
8 | def fonts_dir():
9 | root_dir = os.path.dirname(os.path.dirname(__file__))
10 | yield os.path.join(root_dir, 'fonts')
11 |
12 |
13 | @pytest.fixture
14 | def base_font_path(fonts_dir):
15 | yield os.path.join(fonts_dir, 'Zebrawood.otf')
16 |
17 |
18 | @pytest.fixture
19 | def shadow_font_path(fonts_dir):
20 | yield os.path.join(fonts_dir, 'Zebrawood-Shadow.otf')
21 |
22 |
23 | @pytest.fixture
24 | def fill_font_path(fonts_dir):
25 | yield os.path.join(fonts_dir, 'Zebrawood-Fill.otf')
26 |
27 |
28 | @pytest.fixture
29 | def dots_font_path(fonts_dir):
30 | yield os.path.join(fonts_dir, 'Zebrawood-Dots.otf')
31 |
32 |
33 | @pytest.fixture
34 | def fixtures_dir():
35 | yield os.path.join(os.path.dirname(__file__), 'fixtures')
36 |
--------------------------------------------------------------------------------
/setup.py:
--------------------------------------------------------------------------------
1 | from setuptools import setup
2 |
3 | with open("README.md", "r") as fh:
4 | long_description = fh.read()
5 |
6 | setup(
7 | name="opentypesvg",
8 | use_scm_version={'write_to': 'lib/opentypesvg/__version__.py'},
9 | setup_requires=["setuptools_scm"],
10 | author="Miguel Sousa",
11 | author_email="msousa@adobe.com",
12 | description="Tools for making OpenType-SVG fonts",
13 | long_description=long_description,
14 | long_description_content_type="text/markdown",
15 | url="https://github.com/adobe-type-tools/opentype-svg",
16 | license="MIT",
17 | platforms=["Any"],
18 | package_dir={'': 'lib'},
19 | packages=['opentypesvg'],
20 | python_requires='>=3.6',
21 | install_requires=['fontTools[woff]>=3.1.0'],
22 | entry_points={
23 | 'console_scripts': [
24 | "addsvg = opentypesvg.addsvg:main",
25 | "dumpsvg = opentypesvg.dumpsvg:main",
26 | "fonts2svg = opentypesvg.fonts2svg:main",
27 | ]
28 | },
29 | )
30 |
--------------------------------------------------------------------------------
/.github/workflows/publish.yml:
--------------------------------------------------------------------------------
1 |
2 | name: Publish release
3 |
4 | on:
5 | push:
6 | tags:
7 | - '[0-9]+.[0-9]+.[0-9a-z]+'
8 |
9 | jobs:
10 | deploy:
11 |
12 | runs-on: ubuntu-latest
13 |
14 | steps:
15 | - uses: actions/checkout@v2
16 |
17 | - name: Set up Python
18 | uses: actions/setup-python@v2
19 | with:
20 | python-version: '3.8'
21 |
22 | - name: Install dependencies
23 | run: |
24 | python -m pip install --upgrade pip
25 | pip install setuptools wheel
26 |
27 | - name: Build package
28 | run: python setup.py sdist bdist_wheel
29 |
30 | - name: Publish to PyPI
31 | uses: pypa/gh-action-pypi-publish@release/v1
32 | with:
33 | user: __token__
34 | password: ${{ secrets.PYPI_API_TOKEN }}
35 |
36 | - name: Create GitHub release
37 | uses: softprops/action-gh-release@v1
38 | env:
39 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
40 | with:
41 | prerelease: true
42 | files: ./dist/*
43 |
--------------------------------------------------------------------------------
/LICENSE.md:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2016-2017 Adobe Systems Incorporated
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 |
--------------------------------------------------------------------------------
/.github/workflows/test.yml:
--------------------------------------------------------------------------------
1 |
2 | name: Test package
3 |
4 | on:
5 | push:
6 | paths-ignore: [ '**.md' ]
7 |
8 | pull_request:
9 | branches: [ master ]
10 | paths-ignore: [ '**.md' ]
11 |
12 | workflow_dispatch:
13 | inputs:
14 | reason:
15 | description: 'Reason for running workflow'
16 | required: true
17 |
18 | jobs:
19 | test:
20 |
21 | runs-on: ${{ matrix.os }}
22 |
23 | strategy:
24 | matrix:
25 | os: [ubuntu-latest, macos-latest, windows-latest]
26 | python-version: ["3.8", "3.9", "3.10"]
27 | exclude:
28 | - os: macos-latest
29 | python-version: "3.8"
30 | - os: windows-latest
31 | python-version: "3.8"
32 |
33 | steps:
34 | - name: Log reason (manual run only)
35 | if: github.event_name == 'workflow_dispatch'
36 | run: |
37 | echo "Reason for triggering: ${{ github.event.inputs.reason }}"
38 |
39 | - uses: actions/checkout@v3
40 |
41 | - name: Set up Python ${{ matrix.python-version }}
42 | uses: actions/setup-python@v4
43 | with:
44 | python-version: ${{ matrix.python-version }}
45 |
46 | - name: Install dependencies
47 | run: |
48 | python -m pip install --upgrade pip
49 | python -m pip install wheel flake8 pytest-cov
50 |
51 | - name: Lint with flake8
52 | run: flake8
53 |
54 | - name: Install package
55 | run: python -m pip install .
56 |
57 | - name: Test with pytest
58 | run: pytest -v --cov --cov-report=xml
59 |
60 | - name: Report coverage to Codecov
61 | uses: codecov/codecov-action@v3
62 | with:
63 | name: Python ${{ matrix.python-version }} (${{ matrix.os }})
64 | files: ./coverage.xml
65 |
--------------------------------------------------------------------------------
/tests/fixtures/Y.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/tests/fixtures/A.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/tests/fixtures/Z.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | [](https://pypi.org/project/opentypesvg)
2 | [](https://github.com/adobe-type-tools/opentype-svg/actions/workflows/test.yml)
3 | [](https://codecov.io/gh/adobe-type-tools/opentype-svg)
4 |
5 | # Tools for making OpenType-SVG fonts
6 |
7 | - **addsvg** adds an SVG table to a font, using SVG files provided. The font's format can be either OpenType or TrueType.
8 |
9 | - **dumpsvg** saves the contents of a font's SVG table as individual SVG files. The font's format can be either OpenType, TrueType, WOFF, or WOFF2.
10 |
11 | - **fonts2svg** generates a set of SVG glyph files from one or more fonts and hex colors for each of them. The fonts' format can be either OpenType, TrueType, WOFF, or WOFF2.
12 |
13 |
14 | ### Dependencies
15 |
16 | - Python 3.6 or higher
17 |
18 | - [FontTools](https://github.com/fonttools/fonttools) 3.1.0 or higher
19 |
20 |
21 | ### Installation instructions
22 |
23 | - Make sure you have Python 3.6 (or higher) installed:
24 |
25 | ```sh
26 | python --version
27 | ```
28 |
29 | - Setup a virtual environment:
30 |
31 | ```sh
32 | python -m venv ot-svg
33 | ```
34 |
35 | - Activate the virtual environment:
36 |
37 | - macOS & Linux
38 |
39 | ```sh
40 | source ot-svg/bin/activate
41 | ```
42 |
43 | - Windows
44 |
45 | ```sh
46 | ot-svg\Scripts\activate.bat
47 | ```
48 |
49 | - Install **opentypesvg**:
50 |
51 | ```sh
52 | python -m pip install opentypesvg
53 | ```
54 |
55 | # How to make OpenType-SVG fonts?
56 |
57 | ### Step 1
58 | #### Generate a set of SVG files from a series of fonts and color values.
59 |
60 | 
61 |
62 | fonts2svg -c 99ccff,ff0066,cc0066 fonts/Zebrawood-Shadow.otf fonts/Zebrawood-Fill.otf fonts/Zebrawood-Dots.otf
63 |
64 | ### Step 2
65 | #### Add a set of SVG files to an existing OpenType (or TrueType) font.
66 |
67 | 
68 |
69 | addsvg fonts/SVGs fonts/Zebrawood.otf
70 |
71 | ---
72 |
73 | You can use **Step 2** without doing **Step 1**, but there are a few things you need to be aware of when using the **addsvg** tool:
74 |
75 | * After the SVG files are saved with the authoring application (e.g. Adobe Illustrator, CorelDRAW!, Inkscape) they should be put thru a process that optimizes and cleans up the SVG code; this will slim down the file size while keeping the resulting artwork the same. For this step you can use one of these tools:
76 | * [SVG Cleaner](https://github.com/RazrFalcon/svgcleaner-gui/releases) (GUI version)
77 | * [SVG Cleaner](https://github.com/RazrFalcon/svgcleaner) (command line version)
78 | * [SVG Optimizer](https://github.com/svg/svgo)
79 | * [Scour](https://github.com/scour-project/scour)
80 | * [picosvg](https://github.com/googlefonts/picosvg)
81 |
82 | * **addsvg** requires the SVG files to be named according to the glyphs which they are meant to be associated with. For example, if the glyph in the font is named **ampersand**, the SVG file must be named `ampersand.svg`.
83 |
84 | * **addsvg** expects the color artwork to have been designed at the same size as the glyphs in the font, usually 1000 or 2048 UPM. This means 1 point (pt) in the authoring app equals 1 unit in font coordinates. If the artwork's canvas size is not the same as the font's UPM value, use the `-k` option to prevent the tool from removing the SVG's `viewBox` parameter. Retaining the `viewBox` parameter will enable the artwork to be scaled to the full extent of the viewport (i.e. the font's UPM).
85 |
86 | * If the artwork's `