astroglyphs-2K 0.1.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (39) hide show
  1. astroglyphs_2k-0.1.0/.gitignore +11 -0
  2. astroglyphs_2k-0.1.0/CHANGELOG.md +34 -0
  3. astroglyphs_2k-0.1.0/LICENSE +29 -0
  4. astroglyphs_2k-0.1.0/LICENSES/OFL.txt +93 -0
  5. astroglyphs_2k-0.1.0/PKG-INFO +95 -0
  6. astroglyphs_2k-0.1.0/README.md +67 -0
  7. astroglyphs_2k-0.1.0/pyproject.toml +68 -0
  8. astroglyphs_2k-0.1.0/src/astroglyphs_2K/__init__.py +148 -0
  9. astroglyphs_2k-0.1.0/src/astroglyphs_2K/_data.py +161 -0
  10. astroglyphs_2k-0.1.0/src/astroglyphs_2K/fonts/astroset/AstroMath.otf +0 -0
  11. astroglyphs_2k-0.1.0/src/astroglyphs_2K/fonts/astroset/AstroMath.ttf +0 -0
  12. astroglyphs_2k-0.1.0/src/astroglyphs_2K/fonts/astroset/AstroMath.woff2 +0 -0
  13. astroglyphs_2k-0.1.0/src/astroglyphs_2K/fonts/astroset/AstroSym.otf +0 -0
  14. astroglyphs_2k-0.1.0/src/astroglyphs_2K/fonts/astroset/AstroSym.ttf +0 -0
  15. astroglyphs_2k-0.1.0/src/astroglyphs_2K/fonts/astroset/AstroSym.woff2 +0 -0
  16. astroglyphs_2k-0.1.0/src/astroglyphs_2K/fonts/astroset/AstroSym2.otf +0 -0
  17. astroglyphs_2k-0.1.0/src/astroglyphs_2K/fonts/astroset/AstroSym2.ttf +0 -0
  18. astroglyphs_2k-0.1.0/src/astroglyphs_2K/fonts/astroset/AstroSym2.woff2 +0 -0
  19. astroglyphs_2k-0.1.0/src/astroglyphs_2K/fonts/astroset/AstroText.otf +0 -0
  20. astroglyphs_2k-0.1.0/src/astroglyphs_2K/fonts/astroset/AstroText.ttf +0 -0
  21. astroglyphs_2k-0.1.0/src/astroglyphs_2K/fonts/astroset/AstroText.woff2 +0 -0
  22. astroglyphs_2k-0.1.0/src/astroglyphs_2K/fonts/fullset/AstroMath.otf +0 -0
  23. astroglyphs_2k-0.1.0/src/astroglyphs_2K/fonts/fullset/AstroMath.ttf +0 -0
  24. astroglyphs_2k-0.1.0/src/astroglyphs_2K/fonts/fullset/AstroMath.woff2 +0 -0
  25. astroglyphs_2k-0.1.0/src/astroglyphs_2K/fonts/fullset/AstroSym.otf +0 -0
  26. astroglyphs_2k-0.1.0/src/astroglyphs_2K/fonts/fullset/AstroSym.ttf +0 -0
  27. astroglyphs_2k-0.1.0/src/astroglyphs_2K/fonts/fullset/AstroSym.woff2 +0 -0
  28. astroglyphs_2k-0.1.0/src/astroglyphs_2K/fonts/fullset/AstroSym2.otf +0 -0
  29. astroglyphs_2k-0.1.0/src/astroglyphs_2K/fonts/fullset/AstroSym2.ttf +0 -0
  30. astroglyphs_2k-0.1.0/src/astroglyphs_2K/fonts/fullset/AstroSym2.woff2 +0 -0
  31. astroglyphs_2k-0.1.0/src/astroglyphs_2K/fonts/fullset/AstroText.otf +0 -0
  32. astroglyphs_2k-0.1.0/src/astroglyphs_2K/fonts/fullset/AstroText.ttf +0 -0
  33. astroglyphs_2k-0.1.0/src/astroglyphs_2K/fonts/fullset/AstroText.woff2 +0 -0
  34. astroglyphs_2k-0.1.0/tools/build.py +285 -0
  35. astroglyphs_2k-0.1.0/tools/fonts/NotoSans.ttf +0 -0
  36. astroglyphs_2k-0.1.0/tools/fonts/NotoSansMath.ttf +0 -0
  37. astroglyphs_2k-0.1.0/tools/fonts/NotoSansSymbols.ttf +0 -0
  38. astroglyphs_2k-0.1.0/tools/fonts/NotoSansSymbols2.ttf +0 -0
  39. astroglyphs_2k-0.1.0/tools/fonts/OFL.txt +93 -0
@@ -0,0 +1,11 @@
1
+ *.pyc
2
+ __pycache__/
3
+ .venv/
4
+ venv/
5
+ build/
6
+ dist/
7
+ *.egg-info/
8
+ .pytest_cache/
9
+ .mypy_cache/
10
+ .ruff_cache/
11
+ _apicheck.*
@@ -0,0 +1,34 @@
1
+ # Changelog
2
+
3
+ All notable changes to **astroglyphs_2K** are documented here. The format follows
4
+ [Keep a Changelog](https://keepachangelog.com/) and the project uses
5
+ [Semantic Versioning](https://semver.org/).
6
+
7
+ ## [Unreleased]
8
+
9
+ ## [0.1.0] — 2026-09-15
10
+
11
+ Initial release — curated OFL astrology glyph fonts + metrics + embedding helpers.
12
+
13
+ ### Added
14
+ - **Curated "best of Noto" astrology glyphs**, subset from the Noto family and renamed per the
15
+ OFL Reserved Font Name clause: `AstroSym` (Noto Sans Symbols — planets, nodes, 12 signs,
16
+ asteroids, Chiron, Lilith, Hygeia, aspect symbols), `AstroSym2` (Noto Sans Symbols 2 — Sun,
17
+ Eros, Eris, Sedna), `AstroMath` (Noto Sans Math — ⊗ Part of Fortune), `AstroText` (Noto Sans —
18
+ digits, Latin, ℞ · ° · ′ · ″).
19
+ - **`font_face_css(embed=True, fontset="astroset")`** — self-contained `<style>` inlining the
20
+ fonts as `data:` woff2 URIs. `fontset="fullset"` swaps in the full Noto coverage (text + every
21
+ symbol) under the same family names for anyone who needs more than astrology.
22
+ - **`SYM_FAMILY` / `TXT_FAMILY`** ready-made `font-family` stacks (embedded first, system
23
+ fallbacks after, so `embed=False` degrades gracefully).
24
+ - **`glyph_metrics(ch)` / `GLYPH_METRICS`** — real per-glyph ink-bbox metrics (advance, ymin,
25
+ ymax, xmin, xmax as em fractions) from the source outlines, for precise layout.
26
+ - **Installable font files** — each fontset (`astroset`, `fullset`) is shipped as `.ttf`
27
+ (TrueType, native), `.otf` (OpenType-CFF, converted via qu2cu) and `.woff2` package data.
28
+ `save_fonts(dest, fontset, formats)` writes them to a directory and `font_bytes(family,
29
+ fontset, fmt)` returns the raw bytes — so the glyphs are usable as embedded web fonts *and*
30
+ as installable desktop fonts, not only as base64.
31
+ - Zero runtime dependencies. `tools/build.py` regenerates the data + font files from the vendored
32
+ Noto sources (needs fonttools + brotli; build-only) and is deterministic.
33
+
34
+ [0.1.0]: https://github.com/NoahChristian/astroglyphs_2K/releases/tag/v0.1.0
@@ -0,0 +1,29 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Elizabeth Huston, Ph.D. and Noah Christian, Ph.D.
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
+
23
+ ---
24
+
25
+ The bundled glyph data (the Astro* subset fonts under src/astroglyphs_2K/, both the
26
+ base64 "astroset" data and the "fullset" woff2 files) is derived from the Noto fonts
27
+ and is licensed separately under the SIL Open Font License, Version 1.1 — see
28
+ LICENSES/OFL.txt. The subsets are renamed (Astro*) so they are not distributed under
29
+ a Noto Reserved Font Name.
@@ -0,0 +1,93 @@
1
+ Copyright 2022 The Noto Project Authors (https://github.com/notofonts/latin-greek-cyrillic)
2
+
3
+ This Font Software is licensed under the SIL Open Font License, Version 1.1.
4
+ This license is copied below, and is also available with a FAQ at:
5
+ https://scripts.sil.org/OFL
6
+
7
+
8
+ -----------------------------------------------------------
9
+ SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007
10
+ -----------------------------------------------------------
11
+
12
+ PREAMBLE
13
+ The goals of the Open Font License (OFL) are to stimulate worldwide
14
+ development of collaborative font projects, to support the font creation
15
+ efforts of academic and linguistic communities, and to provide a free and
16
+ open framework in which fonts may be shared and improved in partnership
17
+ with others.
18
+
19
+ The OFL allows the licensed fonts to be used, studied, modified and
20
+ redistributed freely as long as they are not sold by themselves. The
21
+ fonts, including any derivative works, can be bundled, embedded,
22
+ redistributed and/or sold with any software provided that any reserved
23
+ names are not used by derivative works. The fonts and derivatives,
24
+ however, cannot be released under any other type of license. The
25
+ requirement for fonts to remain under this license does not apply
26
+ to any document created using the fonts or their derivatives.
27
+
28
+ DEFINITIONS
29
+ "Font Software" refers to the set of files released by the Copyright
30
+ Holder(s) under this license and clearly marked as such. This may
31
+ include source files, build scripts and documentation.
32
+
33
+ "Reserved Font Name" refers to any names specified as such after the
34
+ copyright statement(s).
35
+
36
+ "Original Version" refers to the collection of Font Software components as
37
+ distributed by the Copyright Holder(s).
38
+
39
+ "Modified Version" refers to any derivative made by adding to, deleting,
40
+ or substituting -- in part or in whole -- any of the components of the
41
+ Original Version, by changing formats or by porting the Font Software to a
42
+ new environment.
43
+
44
+ "Author" refers to any designer, engineer, programmer, technical
45
+ writer or other person who contributed to the Font Software.
46
+
47
+ PERMISSION & CONDITIONS
48
+ Permission is hereby granted, free of charge, to any person obtaining
49
+ a copy of the Font Software, to use, study, copy, merge, embed, modify,
50
+ redistribute, and sell modified and unmodified copies of the Font
51
+ Software, subject to the following conditions:
52
+
53
+ 1) Neither the Font Software nor any of its individual components,
54
+ in Original or Modified Versions, may be sold by itself.
55
+
56
+ 2) Original or Modified Versions of the Font Software may be bundled,
57
+ redistributed and/or sold with any software, provided that each copy
58
+ contains the above copyright notice and this license. These can be
59
+ included either as stand-alone text files, human-readable headers or
60
+ in the appropriate machine-readable metadata fields within text or
61
+ binary files as long as those fields can be easily viewed by the user.
62
+
63
+ 3) No Modified Version of the Font Software may use the Reserved Font
64
+ Name(s) unless explicit written permission is granted by the corresponding
65
+ Copyright Holder. This restriction only applies to the primary font name as
66
+ presented to the users.
67
+
68
+ 4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font
69
+ Software shall not be used to promote, endorse or advertise any
70
+ Modified Version, except to acknowledge the contribution(s) of the
71
+ Copyright Holder(s) and the Author(s) or with their explicit written
72
+ permission.
73
+
74
+ 5) The Font Software, modified or unmodified, in part or in whole,
75
+ must be distributed entirely under this license, and must not be
76
+ distributed under any other license. The requirement for fonts to
77
+ remain under this license does not apply to any document created
78
+ using the Font Software.
79
+
80
+ TERMINATION
81
+ This license becomes null and void if any of the above conditions are
82
+ not met.
83
+
84
+ DISCLAIMER
85
+ THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
86
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF
87
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT
88
+ OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE
89
+ COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
90
+ INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL
91
+ DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
92
+ FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM
93
+ OTHER DEALINGS IN THE FONT SOFTWARE.
@@ -0,0 +1,95 @@
1
+ Metadata-Version: 2.5
2
+ Name: astroglyphs_2K
3
+ Version: 0.1.0
4
+ Summary: Curated OFL astrology glyph fonts (the best of Noto) + metrics + embedding helpers
5
+ Project-URL: Homepage, https://github.com/NoahChristian/astroglyphs_2K
6
+ Project-URL: Repository, https://github.com/NoahChristian/astroglyphs_2K
7
+ Author: Elizabeth Huston, Noah Christian
8
+ License-Expression: MIT
9
+ License-File: LICENSE
10
+ Keywords: astrology,fonts,glyphs,noto,ofl,planets,svg,webfont,zodiac
11
+ Classifier: Development Status :: 4 - Beta
12
+ Classifier: Intended Audience :: Developers
13
+ Classifier: License :: OSI Approved :: MIT License
14
+ Classifier: Operating System :: OS Independent
15
+ Classifier: Programming Language :: Python :: 3
16
+ Classifier: Programming Language :: Python :: 3 :: Only
17
+ Classifier: Topic :: Multimedia :: Graphics
18
+ Classifier: Topic :: Scientific/Engineering :: Astronomy
19
+ Requires-Python: >=3.10
20
+ Provides-Extra: build
21
+ Requires-Dist: brotli>=1.0; extra == 'build'
22
+ Requires-Dist: fonttools>=4.4; extra == 'build'
23
+ Provides-Extra: test
24
+ Requires-Dist: mypy>=1.10; extra == 'test'
25
+ Requires-Dist: pytest>=7; extra == 'test'
26
+ Requires-Dist: ruff>=0.6; extra == 'test'
27
+ Description-Content-Type: text/markdown
28
+
29
+ # astroglyphs_2K
30
+
31
+ Curated **OFL astrology glyph fonts** — the "best of Noto" — plus per-glyph metrics and one-line
32
+ embedding helpers, so any chart renderer gets **deterministic** astrology symbols instead of
33
+ depending on whatever fonts the viewer has installed.
34
+
35
+ The good astrology fonts (Linotype Astrology Pi and friends) are proprietary and can't be
36
+ bundled. astroglyphs_2K subsets the freely-licensed **Noto** family into compact web fonts you
37
+ can inline directly into an SVG or HTML page, and tells you exactly how big each glyph is.
38
+
39
+ ```bash
40
+ pip install astroglyphs_2K
41
+ ```
42
+
43
+ ```python
44
+ import astroglyphs_2K as ag
45
+
46
+ svg = (ag.font_face_css() # <style> with the embedded @font-face rules
47
+ + f'<text font-family={ag.SYM_FAMILY!r}>☉︎ ♄︎ ♏︎</text>'
48
+ + f'<text font-family={ag.TXT_FAMILY!r}>22°℞ 36′</text>')
49
+ ```
50
+
51
+ ## What's inside
52
+
53
+ All glyphs are subset from Noto and **renamed** per the OFL Reserved Font Name clause:
54
+
55
+ | Family | Source (Noto) | Glyphs |
56
+ |---|---|---|
57
+ | `AstroSym` | Noto Sans Symbols | planets (Moon–Pluto), nodes, the 12 signs, asteroids, Chiron, Lilith, Hygeia, aspect symbols |
58
+ | `AstroSym2` | Noto Sans Symbols 2 | the Sun, Eros, Eris, Sedna |
59
+ | `AstroMath` | Noto Sans Math | ⊗ Part of Fortune |
60
+ | `AstroText` | Noto Sans | digits, Latin, `℞` · `°` · `′` · `″` |
61
+
62
+ `SYM_FAMILY` and `TXT_FAMILY` are ready-made `font-family` stacks (embedded families first,
63
+ system fallbacks after), so with `font_face_css(embed=False)` the page degrades gracefully to
64
+ the viewer's own fonts.
65
+
66
+ ## API
67
+
68
+ - `font_face_css(embed=True)` → a `<style>` element inlining every font as a `data:` woff2 URI
69
+ (self-contained; returns `""` when `embed=False`).
70
+ - `SYM_FAMILY`, `TXT_FAMILY` → `font-family` stacks.
71
+ - `glyph_metrics(ch)` → `(advance, ymin, ymax, xmin, xmax)` in fractions of the em (ink bounding
72
+ box from the outline) — for laying glyphs out without guessing.
73
+ - `save_fonts(dest, fontset="astroset", formats=("ttf","otf","woff2"))` → write the packaged
74
+ **installable font files** (TrueType `.ttf`, OpenType-CFF `.otf`, web `.woff2`) into a directory;
75
+ `font_bytes(family, fontset, fmt)` returns one file's raw bytes. Both `astroset` (the compact
76
+ astrology subset) and `fullset` (the whole renamed Noto family) are available.
77
+ - `GLYPH_METRICS`, `SYMBOL_FAMILY_NAMES`, `TEXT_FAMILY_NAME`, `FONT_SETS`, `FONT_FORMATS`,
78
+ `OFL_ATTRIBUTION`.
79
+
80
+ ## Licensing
81
+
82
+ Code: **MIT**. Bundled font data: **SIL Open Font License 1.1** (the subset Noto glyphs) — see
83
+ [`LICENSES/OFL.txt`](LICENSES/OFL.txt) and `astroglyphs_2K.OFL_ATTRIBUTION`. The subsets are
84
+ renamed (`Astro*`) so they are not distributed under a Noto Reserved Font Name.
85
+
86
+ ## Rebuilding the data
87
+
88
+ ```bash
89
+ pip install -e ".[build]" # fonttools + brotli
90
+ python tools/build.py # regenerates src/astroglyphs_2K/_data.py from tools/fonts/*.ttf
91
+ ```
92
+
93
+ Deterministic: the same vendored sources produce the same `_data.py`.
94
+
95
+ MIT © 2026 Elizabeth Huston, Ph.D. and Noah Christian, Ph.D. · bundled glyphs © the Noto Project (OFL 1.1)
@@ -0,0 +1,67 @@
1
+ # astroglyphs_2K
2
+
3
+ Curated **OFL astrology glyph fonts** — the "best of Noto" — plus per-glyph metrics and one-line
4
+ embedding helpers, so any chart renderer gets **deterministic** astrology symbols instead of
5
+ depending on whatever fonts the viewer has installed.
6
+
7
+ The good astrology fonts (Linotype Astrology Pi and friends) are proprietary and can't be
8
+ bundled. astroglyphs_2K subsets the freely-licensed **Noto** family into compact web fonts you
9
+ can inline directly into an SVG or HTML page, and tells you exactly how big each glyph is.
10
+
11
+ ```bash
12
+ pip install astroglyphs_2K
13
+ ```
14
+
15
+ ```python
16
+ import astroglyphs_2K as ag
17
+
18
+ svg = (ag.font_face_css() # <style> with the embedded @font-face rules
19
+ + f'<text font-family={ag.SYM_FAMILY!r}>☉︎ ♄︎ ♏︎</text>'
20
+ + f'<text font-family={ag.TXT_FAMILY!r}>22°℞ 36′</text>')
21
+ ```
22
+
23
+ ## What's inside
24
+
25
+ All glyphs are subset from Noto and **renamed** per the OFL Reserved Font Name clause:
26
+
27
+ | Family | Source (Noto) | Glyphs |
28
+ |---|---|---|
29
+ | `AstroSym` | Noto Sans Symbols | planets (Moon–Pluto), nodes, the 12 signs, asteroids, Chiron, Lilith, Hygeia, aspect symbols |
30
+ | `AstroSym2` | Noto Sans Symbols 2 | the Sun, Eros, Eris, Sedna |
31
+ | `AstroMath` | Noto Sans Math | ⊗ Part of Fortune |
32
+ | `AstroText` | Noto Sans | digits, Latin, `℞` · `°` · `′` · `″` |
33
+
34
+ `SYM_FAMILY` and `TXT_FAMILY` are ready-made `font-family` stacks (embedded families first,
35
+ system fallbacks after), so with `font_face_css(embed=False)` the page degrades gracefully to
36
+ the viewer's own fonts.
37
+
38
+ ## API
39
+
40
+ - `font_face_css(embed=True)` → a `<style>` element inlining every font as a `data:` woff2 URI
41
+ (self-contained; returns `""` when `embed=False`).
42
+ - `SYM_FAMILY`, `TXT_FAMILY` → `font-family` stacks.
43
+ - `glyph_metrics(ch)` → `(advance, ymin, ymax, xmin, xmax)` in fractions of the em (ink bounding
44
+ box from the outline) — for laying glyphs out without guessing.
45
+ - `save_fonts(dest, fontset="astroset", formats=("ttf","otf","woff2"))` → write the packaged
46
+ **installable font files** (TrueType `.ttf`, OpenType-CFF `.otf`, web `.woff2`) into a directory;
47
+ `font_bytes(family, fontset, fmt)` returns one file's raw bytes. Both `astroset` (the compact
48
+ astrology subset) and `fullset` (the whole renamed Noto family) are available.
49
+ - `GLYPH_METRICS`, `SYMBOL_FAMILY_NAMES`, `TEXT_FAMILY_NAME`, `FONT_SETS`, `FONT_FORMATS`,
50
+ `OFL_ATTRIBUTION`.
51
+
52
+ ## Licensing
53
+
54
+ Code: **MIT**. Bundled font data: **SIL Open Font License 1.1** (the subset Noto glyphs) — see
55
+ [`LICENSES/OFL.txt`](LICENSES/OFL.txt) and `astroglyphs_2K.OFL_ATTRIBUTION`. The subsets are
56
+ renamed (`Astro*`) so they are not distributed under a Noto Reserved Font Name.
57
+
58
+ ## Rebuilding the data
59
+
60
+ ```bash
61
+ pip install -e ".[build]" # fonttools + brotli
62
+ python tools/build.py # regenerates src/astroglyphs_2K/_data.py from tools/fonts/*.ttf
63
+ ```
64
+
65
+ Deterministic: the same vendored sources produce the same `_data.py`.
66
+
67
+ MIT © 2026 Elizabeth Huston, Ph.D. and Noah Christian, Ph.D. · bundled glyphs © the Noto Project (OFL 1.1)
@@ -0,0 +1,68 @@
1
+ [build-system]
2
+ requires = ["hatchling"]
3
+ build-backend = "hatchling.build"
4
+
5
+ [project]
6
+ name = "astroglyphs_2K"
7
+ version = "0.1.0"
8
+ description = "Curated OFL astrology glyph fonts (the best of Noto) + metrics + embedding helpers"
9
+ readme = "README.md"
10
+ license = "MIT"
11
+ requires-python = ">=3.10"
12
+ authors = [
13
+ { name = "Elizabeth Huston" },
14
+ { name = "Noah Christian" },
15
+ ]
16
+ keywords = [
17
+ "astrology", "fonts", "glyphs", "svg", "noto", "ofl", "zodiac", "planets", "webfont",
18
+ ]
19
+ classifiers = [
20
+ "Development Status :: 4 - Beta",
21
+ "License :: OSI Approved :: MIT License",
22
+ "Programming Language :: Python :: 3",
23
+ "Programming Language :: Python :: 3 :: Only",
24
+ "Topic :: Multimedia :: Graphics",
25
+ "Topic :: Scientific/Engineering :: Astronomy",
26
+ "Intended Audience :: Developers",
27
+ "Operating System :: OS Independent",
28
+ ]
29
+ # The runtime is pure data + stdlib — no dependencies. The bundled glyphs are subset from the
30
+ # Noto family and licensed under the SIL Open Font License 1.1 (see LICENSES/OFL.txt); the code
31
+ # is MIT. fonttools + brotli are needed only to REBUILD the data (tools/build.py).
32
+ dependencies = []
33
+
34
+ [project.optional-dependencies]
35
+ build = ["fonttools>=4.4", "brotli>=1.0"]
36
+ test = ["pytest>=7", "ruff>=0.6", "mypy>=1.10"]
37
+
38
+ [project.urls]
39
+ Homepage = "https://github.com/NoahChristian/astroglyphs_2K"
40
+ Repository = "https://github.com/NoahChristian/astroglyphs_2K"
41
+
42
+ [tool.hatch.build]
43
+ # ship the generated font files (ttf/otf/woff2 for astroset + fullset) as binary package data
44
+ artifacts = [
45
+ "src/astroglyphs_2K/fonts/astroset/*",
46
+ "src/astroglyphs_2K/fonts/fullset/*",
47
+ ]
48
+
49
+ [tool.hatch.build.targets.wheel]
50
+ packages = ["src/astroglyphs_2K"]
51
+
52
+ [tool.hatch.build.targets.sdist]
53
+ include = ["src/astroglyphs_2K", "tools", "README.md", "CHANGELOG.md", "LICENSE", "LICENSES"]
54
+
55
+ [tool.ruff]
56
+ line-length = 100
57
+ target-version = "py310"
58
+
59
+ [tool.ruff.lint]
60
+ select = ["E", "F", "I", "UP", "B"]
61
+ # E501: the generated _data.py holds long base64 lines. UP031: %-formatting is deliberate.
62
+ ignore = ["E501", "UP031"]
63
+
64
+ [tool.mypy]
65
+ python_version = "3.10"
66
+ files = ["src/astroglyphs_2K"]
67
+ ignore_missing_imports = true
68
+ disallow_untyped_defs = false
@@ -0,0 +1,148 @@
1
+ """astroglyphs_2K — curated OFL astrology glyph fonts (the "best of Noto") + metrics + embedding.
2
+
3
+ A tiny, zero-runtime-dependency toolkit that gives any chart renderer a deterministic,
4
+ embeddable set of astrology glyphs. The good astrology fonts are proprietary; this subsets and
5
+ re-packages the freely-licensed **Noto** family (SIL Open Font License) into compact web fonts
6
+ plus real per-glyph metrics, so charts render identically on every device instead of depending
7
+ on whatever symbol font the viewer happens to have.
8
+
9
+ Glyph routing (all OFL, subset + renamed per the Reserved Font Name clause):
10
+ - **AstroSym** (Noto Sans Symbols) — planets, nodes, 12 signs, asteroids, Chiron, Lilith, Hygeia
11
+ - **AstroSym2** (Noto Sans Symbols 2) — the Sun, Eros, Eris, Sedna
12
+ - **AstroMath** (Noto Sans Math) — ⊗ Part of Fortune
13
+ - **AstroText** (Noto Sans) — digits, Latin, ℞ · ° · ′ · ″
14
+
15
+ Quick use (inline in an SVG or HTML):
16
+ import astroglyphs_2K as ag
17
+ svg = ag.font_face_css() + '<text font-family=%r>%s</text>' % (ag.SYM_FAMILY, "☉︎")
18
+
19
+ Regenerate the bundled data with ``python tools/build.py`` (needs fonttools + brotli; build-only).
20
+ """
21
+
22
+ import base64 as _base64
23
+ import importlib.resources as _res
24
+
25
+ from ._data import ( # noqa: F401
26
+ GLYPH_METRICS,
27
+ OFL_ATTRIBUTION,
28
+ SOURCE_FONT_VERSIONS,
29
+ SYMBOL_FAMILY_NAMES,
30
+ SYMBOLS_WOFF2_B64,
31
+ TEXT_FAMILY_NAME,
32
+ TEXT_WOFF2_B64,
33
+ )
34
+
35
+ __version__ = "0.1.0"
36
+
37
+ # System fallbacks (used when embedding is off, or a viewer strips the embedded face).
38
+ # Family names are single-quoted so the stacks are valid both in a CSS `font-family:` value
39
+ # AND inside a double-quoted SVG/HTML `font-family="..."` attribute (single quotes can't
40
+ # collide with the double-quote delimiter); font-family matching ignores quote style, so the
41
+ # `@font-face` rules below keep their double quotes and still bind to these single-quoted refs.
42
+ _SYM_FALLBACK = "'Segoe UI Symbol','Noto Sans Symbols2','Apple Symbols',system-ui,sans-serif"
43
+ _TXT_FALLBACK = "system-ui,-apple-system,'Segoe UI',Roboto,sans-serif"
44
+
45
+ #: font-family stack for symbol glyphs (embedded families first, then system fallbacks)
46
+ SYM_FAMILY = ",".join("'%s'" % n for n in SYMBOL_FAMILY_NAMES) + "," + _SYM_FALLBACK
47
+ #: font-family stack for text (numerals, labels, ℞/°/′/″)
48
+ TXT_FAMILY = "'%s',%s" % (TEXT_FAMILY_NAME, _TXT_FALLBACK)
49
+
50
+ #: the font file formats shipped as package data for each fontset
51
+ FONT_FORMATS = ("ttf", "otf", "woff2")
52
+ #: the fontsets available as installable/exportable files
53
+ FONT_SETS = ("astroset", "fullset")
54
+
55
+ __all__ = [
56
+ "__version__", "SYM_FAMILY", "TXT_FAMILY", "font_face_css", "glyph_metrics",
57
+ "GLYPH_METRICS", "SYMBOL_FAMILY_NAMES", "TEXT_FAMILY_NAME", "OFL_ATTRIBUTION",
58
+ "SOURCE_FONT_VERSIONS", "save_fonts", "font_bytes", "FONT_FORMATS", "FONT_SETS",
59
+ ]
60
+
61
+
62
+ def _face(fam, b64, weight=False):
63
+ w = ";font-weight:100 900" if weight else ""
64
+ return ('@font-face{font-family:"%s";src:url(data:font/woff2;base64,%s) '
65
+ 'format("woff2")%s;}' % (fam, b64, w))
66
+
67
+
68
+ def _fullset_b64(fam):
69
+ """Base64 of a full-coverage woff2, read from package data (the 'fullset' perk)."""
70
+ return _base64.b64encode(font_bytes(fam, "fullset", "woff2")).decode("ascii")
71
+
72
+
73
+ def _families():
74
+ return list(SYMBOL_FAMILY_NAMES) + [TEXT_FAMILY_NAME]
75
+
76
+
77
+ def font_bytes(family: str, fontset: str = "astroset", fmt: str = "ttf") -> bytes:
78
+ """Raw bytes of one packaged font file — ``family`` (e.g. "AstroSym", "AstroText"),
79
+ ``fontset`` ("astroset" or "fullset") and ``fmt`` ("ttf", "otf" or "woff2")."""
80
+ if fontset not in FONT_SETS:
81
+ raise ValueError("fontset must be one of %r, not %r" % (FONT_SETS, fontset))
82
+ if fmt not in FONT_FORMATS:
83
+ raise ValueError("fmt must be one of %r, not %r" % (FONT_FORMATS, fmt))
84
+ if family not in _families():
85
+ raise ValueError("family must be one of %r, not %r" % (_families(), family))
86
+ return (_res.files(__name__).joinpath("fonts").joinpath(fontset)
87
+ .joinpath(family + "." + fmt).read_bytes())
88
+
89
+
90
+ def save_fonts(dest_dir, fontset: str = "astroset", formats=("ttf", "otf", "woff2")) -> list:
91
+ """Write the packaged font files for ``fontset`` into ``dest_dir`` and return the paths.
92
+
93
+ These are the renamed OFL glyph fonts: installable desktop fonts (``ttf`` native, ``otf``/CFF)
94
+ plus the web font (``woff2``). ``"astroset"`` is the compact astrology subset; ``"fullset"`` is
95
+ the whole renamed Noto family (much larger). Example — export installable fonts::
96
+
97
+ import astroglyphs_2K as ag
98
+ ag.save_fonts("~/astro-fonts", fontset="fullset", formats=("ttf", "otf"))
99
+ """
100
+ import os
101
+ import pathlib
102
+ dest = pathlib.Path(os.path.expanduser(str(dest_dir)))
103
+ dest.mkdir(parents=True, exist_ok=True)
104
+ written = []
105
+ for fam in _families():
106
+ for fmt in formats:
107
+ out = dest / (fam + "." + fmt)
108
+ out.write_bytes(font_bytes(fam, fontset, fmt))
109
+ written.append(out)
110
+ return written
111
+
112
+
113
+ def font_face_css(embed: bool = True, fontset: str = "astroset") -> str:
114
+ """Return a ``<style>`` element with the ``@font-face`` rules for the embedded fonts.
115
+
116
+ Each face inlines its woff2 as a ``data:`` URI, so the output is self-contained (no network,
117
+ no external files). Returns ``""`` when ``embed`` is False — then ``SYM_FAMILY`` / ``TXT_FAMILY``
118
+ fall back to the viewer's system fonts.
119
+
120
+ ``fontset``:
121
+ - ``"astroset"`` (default) — the compact curated astrology subset (~60 KB total). Covers
122
+ everything astrology renders; the metrics in ``GLYPH_METRICS`` describe exactly this set.
123
+ - ``"fullset"`` — the whole megacollection: the FULL Noto fonts (text + every symbol),
124
+ under the same family names, for anyone who wants coverage beyond astrology. Much larger
125
+ (a few MB inlined per document) — turn it up to 11 only when you need it.
126
+ """
127
+ if not embed:
128
+ return ""
129
+ if fontset == "astroset":
130
+ faces = [_face(fam, b64)
131
+ for fam, b64 in zip(SYMBOL_FAMILY_NAMES, SYMBOLS_WOFF2_B64, strict=True)]
132
+ faces.append(_face(TEXT_FAMILY_NAME, TEXT_WOFF2_B64, weight=True))
133
+ elif fontset == "fullset":
134
+ faces = [_face(fam, _fullset_b64(fam)) for fam in SYMBOL_FAMILY_NAMES]
135
+ faces.append(_face(TEXT_FAMILY_NAME, _fullset_b64(TEXT_FAMILY_NAME), weight=True))
136
+ else:
137
+ raise ValueError("fontset must be 'astroset' or 'fullset', not %r" % fontset)
138
+ return "<style>" + "".join(faces) + "</style>"
139
+
140
+
141
+ def glyph_metrics(ch):
142
+ """Metrics for a glyph as ``(advance, ymin, ymax, xmin, xmax)`` in fractions of the em
143
+ (ink bounding box from the outline), or ``None`` if the glyph isn't in the inventory.
144
+
145
+ ``ch`` may be a single-character string or an int codepoint.
146
+ """
147
+ cp = ord(ch) if isinstance(ch, str) else int(ch)
148
+ return GLYPH_METRICS.get(cp)