rotulo 0.2.0__tar.gz → 0.3.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.
- rotulo-0.3.0/.github/workflows/pages.yml +41 -0
- {rotulo-0.2.0 → rotulo-0.3.0}/.gitignore +2 -0
- {rotulo-0.2.0 → rotulo-0.3.0}/PKG-INFO +10 -4
- {rotulo-0.2.0 → rotulo-0.3.0}/README.md +9 -3
- rotulo-0.3.0/demo/index.html +76 -0
- rotulo-0.3.0/demo/main.js +27 -0
- rotulo-0.3.0/demo/styles.css +232 -0
- {rotulo-0.2.0 → rotulo-0.3.0}/docs/CHANGELOG.md +10 -0
- {rotulo-0.2.0 → rotulo-0.3.0}/pyproject.toml +1 -1
- {rotulo-0.2.0 → rotulo-0.3.0}/src/rotulo/build.py +1 -1
- {rotulo-0.2.0 → rotulo-0.3.0}/src/rotulo/context.py +1 -0
- {rotulo-0.2.0 → rotulo-0.3.0}/src/rotulo/figures.py +1 -1
- {rotulo-0.2.0 → rotulo-0.3.0}/src/rotulo/params.py +5 -3
- {rotulo-0.2.0 → rotulo-0.3.0}/src/rotulo/symbols.py +1 -1
- {rotulo-0.2.0 → rotulo-0.3.0}/src/rotulo/variable.py +1 -1
- {rotulo-0.2.0 → rotulo-0.3.0}/web/package.json +1 -1
- {rotulo-0.2.0 → rotulo-0.3.0}/.github/assets/icon-dark.svg +0 -0
- {rotulo-0.2.0 → rotulo-0.3.0}/.github/assets/icon-light.svg +0 -0
- {rotulo-0.2.0 → rotulo-0.3.0}/.github/assets/specimen.png +0 -0
- {rotulo-0.2.0 → rotulo-0.3.0}/.github/workflows/ci.yml +0 -0
- {rotulo-0.2.0 → rotulo-0.3.0}/.github/workflows/release.yml +0 -0
- {rotulo-0.2.0 → rotulo-0.3.0}/LICENSE +0 -0
- {rotulo-0.2.0 → rotulo-0.3.0}/src/rotulo/__init__.py +0 -0
- {rotulo-0.2.0 → rotulo-0.3.0}/src/rotulo/__main__.py +0 -0
- {rotulo-0.2.0 → rotulo-0.3.0}/src/rotulo/accents.py +0 -0
- {rotulo-0.2.0 → rotulo-0.3.0}/src/rotulo/capsule.py +0 -0
- {rotulo-0.2.0 → rotulo-0.3.0}/src/rotulo/chars.py +0 -0
- {rotulo-0.2.0 → rotulo-0.3.0}/src/rotulo/glyphset.py +0 -0
- {rotulo-0.2.0 → rotulo-0.3.0}/src/rotulo/lowercase.py +0 -0
- {rotulo-0.2.0 → rotulo-0.3.0}/src/rotulo/outline.py +0 -0
- {rotulo-0.2.0 → rotulo-0.3.0}/src/rotulo/py.typed +0 -0
- {rotulo-0.2.0 → rotulo-0.3.0}/src/rotulo/skeleton.py +0 -0
- {rotulo-0.2.0 → rotulo-0.3.0}/src/rotulo/spacing.py +0 -0
- {rotulo-0.2.0 → rotulo-0.3.0}/src/rotulo/uppercase.py +0 -0
- {rotulo-0.2.0 → rotulo-0.3.0}/src/rotulo/web.py +0 -0
- {rotulo-0.2.0 → rotulo-0.3.0}/tests/__init__.py +0 -0
- {rotulo-0.2.0 → rotulo-0.3.0}/tests/test_build.py +0 -0
- {rotulo-0.2.0 → rotulo-0.3.0}/tests/test_skeleton.py +0 -0
- {rotulo-0.2.0 → rotulo-0.3.0}/web/index.d.ts +0 -0
- {rotulo-0.2.0 → rotulo-0.3.0}/web/rotulo.css +0 -0
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
name: demo
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
branches: [develop]
|
|
6
|
+
workflow_dispatch:
|
|
7
|
+
|
|
8
|
+
permissions:
|
|
9
|
+
contents: read
|
|
10
|
+
pages: write
|
|
11
|
+
id-token: write
|
|
12
|
+
|
|
13
|
+
concurrency:
|
|
14
|
+
group: pages
|
|
15
|
+
cancel-in-progress: true
|
|
16
|
+
|
|
17
|
+
jobs:
|
|
18
|
+
build:
|
|
19
|
+
runs-on: ubuntu-latest
|
|
20
|
+
steps:
|
|
21
|
+
- uses: actions/checkout@v7
|
|
22
|
+
- uses: actions/setup-python@v7
|
|
23
|
+
with:
|
|
24
|
+
python-version: '3.12'
|
|
25
|
+
- run: python -m pip install .
|
|
26
|
+
- run: python -m rotulo --out build --web demo/fonts
|
|
27
|
+
- run: cp web/rotulo.css demo/
|
|
28
|
+
- uses: actions/configure-pages@v5
|
|
29
|
+
- uses: actions/upload-pages-artifact@v3
|
|
30
|
+
with:
|
|
31
|
+
path: demo
|
|
32
|
+
|
|
33
|
+
deploy:
|
|
34
|
+
needs: build
|
|
35
|
+
runs-on: ubuntu-latest
|
|
36
|
+
environment:
|
|
37
|
+
name: github-pages
|
|
38
|
+
url: ${{ steps.deployment.outputs.page_url }}
|
|
39
|
+
steps:
|
|
40
|
+
- id: deployment
|
|
41
|
+
uses: actions/deploy-pages@v4
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.5
|
|
2
2
|
Name: rotulo
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.3.0
|
|
4
4
|
Summary: Monoline typeface generated from skeletons: strokes of lines and arcs expanded with a round pen.
|
|
5
5
|
Author: Edgar Villarreal
|
|
6
6
|
License-Expression: OFL-1.1
|
|
@@ -30,6 +30,8 @@ Monoline typeface generated from skeletons: strokes of lines and arcs expanded w
|
|
|
30
30
|
|
|
31
31
|

|
|
32
32
|
|
|
33
|
+
**[Live demo](https://ghegar.github.io/rotulo/)**
|
|
34
|
+
|
|
33
35
|
Every letter is a skeleton of straight lines and arcs drawn in code, never a hand-drawn outline. The
|
|
34
36
|
generator expands each skeleton with a round pen and writes TrueType and WOFF2 fonts. Weight is the
|
|
35
37
|
pen width, so the family is a variable font from 200 to 700. A reading cut, **Lectura**, adds weight, spacing and
|
|
@@ -106,9 +108,10 @@ flag on `1` and a straight `9`.
|
|
|
106
108
|
|
|
107
109
|
| Field | Default | What it controls |
|
|
108
110
|
|---|---|---|
|
|
109
|
-
| `weight` |
|
|
111
|
+
| `weight` | 46 | Pen width |
|
|
110
112
|
| `x_height`, `cap_height` | 425, 700 | Body and capital heights |
|
|
111
|
-
| `ascender`, `descender` | 840, −
|
|
113
|
+
| `ascender`, `descender` | 840, −415 | Shared by every letter with a tail; the descender matches the ascender's reach above the x-height |
|
|
114
|
+
| `sign_descender` | −180 | Depth of brackets, braces, parentheses, `\|`, `/` and `_` |
|
|
112
115
|
| `corner` | 50 | Radius used to round every skeleton vertex |
|
|
113
116
|
| `gap` | 110 | Space between a stroke and a floating detail |
|
|
114
117
|
| `spacing`, `word_spacing` | 1.5, 1.0 | Side bearings and space width |
|
|
@@ -120,7 +123,7 @@ from pathlib import Path
|
|
|
120
123
|
|
|
121
124
|
from rotulo import DISPLAY, build_font
|
|
122
125
|
|
|
123
|
-
print(build_font(replace(DISPLAY, weight=
|
|
126
|
+
print(build_font(replace(DISPLAY, weight=70), "Medium", 400, Path("build")))
|
|
124
127
|
```
|
|
125
128
|
|
|
126
129
|
## Known limitations
|
|
@@ -139,6 +142,9 @@ ruff check src tests && ruff format --check src tests
|
|
|
139
142
|
mypy
|
|
140
143
|
```
|
|
141
144
|
|
|
145
|
+
The demo in `demo/` is a static specimen: build the fonts into it with
|
|
146
|
+
`python -m rotulo --out build --web demo/fonts && cp web/rotulo.css demo/` and serve the folder.
|
|
147
|
+
|
|
142
148
|
The tests build every font and check heights against the skeleton, kerning, the optional color layers, `ss01`,
|
|
143
149
|
hinting and that the variable font interpolates every glyph.
|
|
144
150
|
|
|
@@ -6,6 +6,8 @@ Monoline typeface generated from skeletons: strokes of lines and arcs expanded w
|
|
|
6
6
|
|
|
7
7
|

|
|
8
8
|
|
|
9
|
+
**[Live demo](https://ghegar.github.io/rotulo/)**
|
|
10
|
+
|
|
9
11
|
Every letter is a skeleton of straight lines and arcs drawn in code, never a hand-drawn outline. The
|
|
10
12
|
generator expands each skeleton with a round pen and writes TrueType and WOFF2 fonts. Weight is the
|
|
11
13
|
pen width, so the family is a variable font from 200 to 700. A reading cut, **Lectura**, adds weight, spacing and
|
|
@@ -82,9 +84,10 @@ flag on `1` and a straight `9`.
|
|
|
82
84
|
|
|
83
85
|
| Field | Default | What it controls |
|
|
84
86
|
|---|---|---|
|
|
85
|
-
| `weight` |
|
|
87
|
+
| `weight` | 46 | Pen width |
|
|
86
88
|
| `x_height`, `cap_height` | 425, 700 | Body and capital heights |
|
|
87
|
-
| `ascender`, `descender` | 840, −
|
|
89
|
+
| `ascender`, `descender` | 840, −415 | Shared by every letter with a tail; the descender matches the ascender's reach above the x-height |
|
|
90
|
+
| `sign_descender` | −180 | Depth of brackets, braces, parentheses, `\|`, `/` and `_` |
|
|
88
91
|
| `corner` | 50 | Radius used to round every skeleton vertex |
|
|
89
92
|
| `gap` | 110 | Space between a stroke and a floating detail |
|
|
90
93
|
| `spacing`, `word_spacing` | 1.5, 1.0 | Side bearings and space width |
|
|
@@ -96,7 +99,7 @@ from pathlib import Path
|
|
|
96
99
|
|
|
97
100
|
from rotulo import DISPLAY, build_font
|
|
98
101
|
|
|
99
|
-
print(build_font(replace(DISPLAY, weight=
|
|
102
|
+
print(build_font(replace(DISPLAY, weight=70), "Medium", 400, Path("build")))
|
|
100
103
|
```
|
|
101
104
|
|
|
102
105
|
## Known limitations
|
|
@@ -115,6 +118,9 @@ ruff check src tests && ruff format --check src tests
|
|
|
115
118
|
mypy
|
|
116
119
|
```
|
|
117
120
|
|
|
121
|
+
The demo in `demo/` is a static specimen: build the fonts into it with
|
|
122
|
+
`python -m rotulo --out build --web demo/fonts && cp web/rotulo.css demo/` and serve the folder.
|
|
123
|
+
|
|
118
124
|
The tests build every font and check heights against the skeleton, kerning, the optional color layers, `ss01`,
|
|
119
125
|
hinting and that the variable font interpolates every glyph.
|
|
120
126
|
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
<!doctype html>
|
|
2
|
+
<html lang="en">
|
|
3
|
+
<head>
|
|
4
|
+
<meta charset="UTF-8" />
|
|
5
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
|
6
|
+
<title>rotulo</title>
|
|
7
|
+
<link rel="icon" href="data:," />
|
|
8
|
+
<link rel="stylesheet" href="./styles.css" />
|
|
9
|
+
</head>
|
|
10
|
+
<body>
|
|
11
|
+
<main class="wrap">
|
|
12
|
+
<header class="top">
|
|
13
|
+
<h1>rotulo</h1>
|
|
14
|
+
<p>Monoline typeface generated from skeletons: strokes of lines and arcs expanded with a round pen.</p>
|
|
15
|
+
<nav>
|
|
16
|
+
<a href="https://github.com/GHEgar/rotulo">GitHub</a>
|
|
17
|
+
<a href="https://www.npmjs.com/package/rotulo">npm</a>
|
|
18
|
+
<a href="https://pypi.org/project/rotulo/">PyPI</a>
|
|
19
|
+
<a href="https://github.com/GHEgar/rotulo/releases/latest">Download TTF</a>
|
|
20
|
+
</nav>
|
|
21
|
+
</header>
|
|
22
|
+
|
|
23
|
+
<section class="controls">
|
|
24
|
+
<label for="weight">Weight <output id="weight-out">400</output></label>
|
|
25
|
+
<input id="weight" type="range" min="200" max="700" step="1" value="400" />
|
|
26
|
+
<label for="size">Size <output id="size-out">64</output></label>
|
|
27
|
+
<input id="size" type="range" min="12" max="160" step="1" value="64" />
|
|
28
|
+
<label class="check"><input id="reading" type="checkbox" /> Reading forms (ss01)</label>
|
|
29
|
+
</section>
|
|
30
|
+
|
|
31
|
+
<section class="sample" id="sample" contenteditable="true" spellcheck="false">Río Santiago</section>
|
|
32
|
+
|
|
33
|
+
<section class="grid">
|
|
34
|
+
<div>
|
|
35
|
+
<h2>Lowercase</h2>
|
|
36
|
+
<p class="glyphs">abcdefghijklmnñopqrstuvwxyz</p>
|
|
37
|
+
</div>
|
|
38
|
+
<div>
|
|
39
|
+
<h2>Uppercase</h2>
|
|
40
|
+
<p class="glyphs">ABCDEFGHIJKLMNÑOPQRSTUVWXYZ</p>
|
|
41
|
+
</div>
|
|
42
|
+
<div>
|
|
43
|
+
<h2>Figures and signs</h2>
|
|
44
|
+
<p class="glyphs">0123456789 &@#%€$+=*_ [](){}<>|~ ¿?¡! «» “” … · —</p>
|
|
45
|
+
</div>
|
|
46
|
+
<div>
|
|
47
|
+
<h2>Accents</h2>
|
|
48
|
+
<p class="glyphs">áéíóúüñ àèìòù âêîôû ãõ ç ëïÿ ÁÉÍÓÚÜÑ ÀÈÌÒÙ ÂÊÎÔÛ ÃÕ Ç</p>
|
|
49
|
+
</div>
|
|
50
|
+
</section>
|
|
51
|
+
|
|
52
|
+
<section class="weights" id="weights"></section>
|
|
53
|
+
|
|
54
|
+
<section class="reading">
|
|
55
|
+
<h2>Rotulo Lectura</h2>
|
|
56
|
+
<p>A heavier, wider-spaced cut with letters that are hard to mirror, meant for long reading.</p>
|
|
57
|
+
<p class="lectura">Un buen mapa no se nota: el lector simplemente llega a donde quería ir. Las avenidas principales llevan un trazo ancho y las calles pequeñas uno fino; los nombres se leen en cualquier ángulo y sobre cualquier fondo. bdpq Il1 69</p>
|
|
58
|
+
</section>
|
|
59
|
+
|
|
60
|
+
<section class="map">
|
|
61
|
+
<h2>Map labels</h2>
|
|
62
|
+
<svg viewBox="0 0 800 340" role="img" aria-label="Map labels set in Rotulo">
|
|
63
|
+
<rect width="800" height="340" class="land" />
|
|
64
|
+
<path d="M-20 280 C 200 230, 420 310, 820 260" class="water" />
|
|
65
|
+
<path d="M-20 130 L 820 80 M 300 -20 L 340 360 M 620 -20 L 580 360" class="road" />
|
|
66
|
+
<text x="470" y="64" class="city">GUADALAJARA</text>
|
|
67
|
+
<text x="150" y="200" class="town">Zapopan</text>
|
|
68
|
+
<text x="160" y="120" class="street" transform="rotate(-3.4 160 120)">Av. Vallarta</text>
|
|
69
|
+
<text x="200" y="252" class="river" transform="rotate(-6 200 252)">Río Santiago</text>
|
|
70
|
+
<text x="690" y="328" class="coord">20°40′ N 103°21′ O</text>
|
|
71
|
+
</svg>
|
|
72
|
+
</section>
|
|
73
|
+
</main>
|
|
74
|
+
<script src="./main.js"></script>
|
|
75
|
+
</body>
|
|
76
|
+
</html>
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
const root = document.documentElement;
|
|
2
|
+
const weight = document.getElementById('weight');
|
|
3
|
+
const size = document.getElementById('size');
|
|
4
|
+
const reading = document.getElementById('reading');
|
|
5
|
+
|
|
6
|
+
const update = () => {
|
|
7
|
+
root.style.setProperty('--weight', weight.value);
|
|
8
|
+
root.style.setProperty('--size', `${size.value}px`);
|
|
9
|
+
document.getElementById('weight-out').textContent = weight.value;
|
|
10
|
+
document.getElementById('size-out').textContent = size.value;
|
|
11
|
+
document.body.classList.toggle('reading-forms', reading.checked);
|
|
12
|
+
};
|
|
13
|
+
|
|
14
|
+
const weights = document.getElementById('weights');
|
|
15
|
+
for (const value of [200, 300, 400, 500, 600, 700]) {
|
|
16
|
+
const line = document.createElement('p');
|
|
17
|
+
line.style.fontWeight = String(value);
|
|
18
|
+
const label = document.createElement('span');
|
|
19
|
+
label.textContent = String(value);
|
|
20
|
+
line.append(label, document.createTextNode('Exportar mapa de Guadalajara'));
|
|
21
|
+
weights.append(line);
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
weight.addEventListener('input', update);
|
|
25
|
+
size.addEventListener('input', update);
|
|
26
|
+
reading.addEventListener('change', update);
|
|
27
|
+
update();
|
|
@@ -0,0 +1,232 @@
|
|
|
1
|
+
@import url('./rotulo.css');
|
|
2
|
+
|
|
3
|
+
:root {
|
|
4
|
+
--bg: #f3f4f1;
|
|
5
|
+
--card: #ffffff;
|
|
6
|
+
--ink: #1d2327;
|
|
7
|
+
--muted: #66706f;
|
|
8
|
+
--line: #dde1dc;
|
|
9
|
+
--accent: #2f5d62;
|
|
10
|
+
--land: #eceee6;
|
|
11
|
+
--water: #c9dde0;
|
|
12
|
+
--road: #ffffff;
|
|
13
|
+
--weight: 400;
|
|
14
|
+
--size: 64px;
|
|
15
|
+
color-scheme: light dark;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
@media (prefers-color-scheme: dark) {
|
|
19
|
+
:root {
|
|
20
|
+
--bg: #161a1b;
|
|
21
|
+
--card: #1f2526;
|
|
22
|
+
--ink: #e6ebe8;
|
|
23
|
+
--muted: #93a09d;
|
|
24
|
+
--line: #2f3739;
|
|
25
|
+
--accent: #7fb7b5;
|
|
26
|
+
--land: #20272a;
|
|
27
|
+
--water: #1d3337;
|
|
28
|
+
--road: #2c3437;
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
* {
|
|
33
|
+
box-sizing: border-box;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
body {
|
|
37
|
+
margin: 0;
|
|
38
|
+
background: var(--bg);
|
|
39
|
+
color: var(--ink);
|
|
40
|
+
font: 16px/1.5 'Rotulo', system-ui, sans-serif;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
.wrap {
|
|
44
|
+
max-width: 1080px;
|
|
45
|
+
margin: 0 auto;
|
|
46
|
+
padding: 40px 20px 80px;
|
|
47
|
+
display: grid;
|
|
48
|
+
gap: 28px;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
.top h1 {
|
|
52
|
+
margin: 0;
|
|
53
|
+
font-size: 72px;
|
|
54
|
+
font-weight: 300;
|
|
55
|
+
line-height: 1;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
.top p {
|
|
59
|
+
margin: 8px 0 12px;
|
|
60
|
+
color: var(--muted);
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
nav {
|
|
64
|
+
display: flex;
|
|
65
|
+
gap: 16px;
|
|
66
|
+
flex-wrap: wrap;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
a {
|
|
70
|
+
color: var(--accent);
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
h2 {
|
|
74
|
+
margin: 0 0 8px;
|
|
75
|
+
font-size: 13px;
|
|
76
|
+
font-weight: 500;
|
|
77
|
+
letter-spacing: 0.08em;
|
|
78
|
+
text-transform: uppercase;
|
|
79
|
+
color: var(--muted);
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
.controls {
|
|
83
|
+
position: sticky;
|
|
84
|
+
top: 0;
|
|
85
|
+
z-index: 1;
|
|
86
|
+
display: grid;
|
|
87
|
+
grid-template-columns: auto minmax(120px, 1fr) auto minmax(120px, 1fr) auto;
|
|
88
|
+
gap: 10px 14px;
|
|
89
|
+
align-items: center;
|
|
90
|
+
padding: 12px 16px;
|
|
91
|
+
background: var(--card);
|
|
92
|
+
border: 1px solid var(--line);
|
|
93
|
+
border-radius: 12px;
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
.controls input[type='range'] {
|
|
97
|
+
accent-color: var(--accent);
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
output {
|
|
101
|
+
font-variant-numeric: tabular-nums;
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
.sample {
|
|
105
|
+
font-size: var(--size);
|
|
106
|
+
font-weight: var(--weight);
|
|
107
|
+
line-height: 1.1;
|
|
108
|
+
outline: none;
|
|
109
|
+
overflow-wrap: anywhere;
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
.reading-forms .sample,
|
|
113
|
+
.reading-forms .glyphs {
|
|
114
|
+
font-feature-settings: 'ss01';
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
.grid {
|
|
118
|
+
display: grid;
|
|
119
|
+
grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));
|
|
120
|
+
gap: 16px;
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
.grid > div,
|
|
124
|
+
.reading,
|
|
125
|
+
.map {
|
|
126
|
+
background: var(--card);
|
|
127
|
+
border: 1px solid var(--line);
|
|
128
|
+
border-radius: 12px;
|
|
129
|
+
padding: 16px;
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
.glyphs {
|
|
133
|
+
margin: 0;
|
|
134
|
+
font-size: 28px;
|
|
135
|
+
font-weight: var(--weight);
|
|
136
|
+
line-height: 1.4;
|
|
137
|
+
overflow-wrap: anywhere;
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
.weights {
|
|
141
|
+
display: grid;
|
|
142
|
+
gap: 4px;
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
.weights p {
|
|
146
|
+
margin: 0;
|
|
147
|
+
font-size: 32px;
|
|
148
|
+
display: flex;
|
|
149
|
+
gap: 16px;
|
|
150
|
+
align-items: baseline;
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
.weights span {
|
|
154
|
+
font-size: 12px;
|
|
155
|
+
color: var(--muted);
|
|
156
|
+
min-width: 3ch;
|
|
157
|
+
font-variant-numeric: tabular-nums;
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
.reading p {
|
|
161
|
+
margin: 0 0 8px;
|
|
162
|
+
color: var(--muted);
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
.lectura {
|
|
166
|
+
font-family: 'Rotulo Lectura', 'Rotulo', sans-serif;
|
|
167
|
+
font-size: 20px;
|
|
168
|
+
line-height: 1.7;
|
|
169
|
+
color: var(--ink) !important;
|
|
170
|
+
max-width: 65ch;
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
.map svg {
|
|
174
|
+
width: 100%;
|
|
175
|
+
height: auto;
|
|
176
|
+
display: block;
|
|
177
|
+
border-radius: 8px;
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
.land {
|
|
181
|
+
fill: var(--land);
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
.water {
|
|
185
|
+
fill: none;
|
|
186
|
+
stroke: var(--water);
|
|
187
|
+
stroke-width: 24;
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
.road {
|
|
191
|
+
fill: none;
|
|
192
|
+
stroke: var(--road);
|
|
193
|
+
stroke-width: 10;
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
.map text {
|
|
197
|
+
fill: var(--ink);
|
|
198
|
+
text-anchor: middle;
|
|
199
|
+
paint-order: stroke;
|
|
200
|
+
stroke: var(--land);
|
|
201
|
+
stroke-width: 4px;
|
|
202
|
+
stroke-linejoin: round;
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
.city {
|
|
206
|
+
font-size: 30px;
|
|
207
|
+
font-weight: 500;
|
|
208
|
+
letter-spacing: 0.08em;
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
.town {
|
|
212
|
+
font-size: 20px;
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
.street,
|
|
216
|
+
.river {
|
|
217
|
+
font-size: 14px;
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
.coord {
|
|
221
|
+
font-size: 11px;
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
@media (max-width: 640px) {
|
|
225
|
+
.controls {
|
|
226
|
+
grid-template-columns: auto 1fr;
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
.top h1 {
|
|
230
|
+
font-size: 52px;
|
|
231
|
+
}
|
|
232
|
+
}
|
|
@@ -5,6 +5,16 @@ Formato basado en [Keep a Changelog](https://keepachangelog.com/es-ES/1.1.0/) y
|
|
|
5
5
|
|
|
6
6
|
## [No publicado]
|
|
7
7
|
|
|
8
|
+
## [0.3.0] - 2026-10-16
|
|
9
|
+
|
|
10
|
+
### Cambiado
|
|
11
|
+
|
|
12
|
+
- Las colas descendentes (`g`, `j`, `p`, `q`, `y`) bajan lo mismo que suben las ascendentes sobre la
|
|
13
|
+
altura x: descendente −415 en Display y −370 en Lectura. Corchetes, llaves, paréntesis, `|`, `/` y `_`
|
|
14
|
+
conservan la profundidad de −180, en el nuevo `sign_descender`.
|
|
15
|
+
- Trazo un 15 % más grueso en toda la rampa: 46 en Display (peso 200), 86 en el peso 500 y en Lectura,
|
|
16
|
+
y 122 en el peso 700.
|
|
17
|
+
|
|
8
18
|
## [0.2.0] - 2026-10-16
|
|
9
19
|
|
|
10
20
|
### Cambiado
|
|
@@ -10,7 +10,7 @@ from rotulo.params import Params
|
|
|
10
10
|
from rotulo.spacing import kerning
|
|
11
11
|
|
|
12
12
|
FAMILY = "Rotulo"
|
|
13
|
-
VERSION = "0.
|
|
13
|
+
VERSION = "0.3.0"
|
|
14
14
|
LICENSE = "This Font Software is licensed under the SIL Open Font License, Version 1.1."
|
|
15
15
|
LICENSE_URL = "https://openfontlicense.org"
|
|
16
16
|
DETAIL_LIGHT = (0x3D / 255, 0x8A / 255, 0x8F / 255, 1.0)
|
|
@@ -10,11 +10,12 @@ GForm = Literal["bar", "curl"]
|
|
|
10
10
|
|
|
11
11
|
@dataclass(frozen=True)
|
|
12
12
|
class Params:
|
|
13
|
-
weight: float =
|
|
13
|
+
weight: float = 46
|
|
14
14
|
x_height: float = 425
|
|
15
15
|
cap_height: float = 700
|
|
16
16
|
ascender: float = 840
|
|
17
|
-
descender: float = -
|
|
17
|
+
descender: float = -415
|
|
18
|
+
sign_descender: float = -180
|
|
18
19
|
width: float = 1.0
|
|
19
20
|
aperture: float = 30
|
|
20
21
|
gap: float = 110
|
|
@@ -43,8 +44,9 @@ class Params:
|
|
|
43
44
|
DISPLAY = Params()
|
|
44
45
|
READING = replace(
|
|
45
46
|
DISPLAY,
|
|
46
|
-
weight=
|
|
47
|
+
weight=86,
|
|
47
48
|
x_height=470,
|
|
49
|
+
descender=-370,
|
|
48
50
|
spacing=1.8,
|
|
49
51
|
word_spacing=1.6,
|
|
50
52
|
l_form="tail",
|
|
@@ -50,7 +50,7 @@ def _compatible(sets: list[GlyphSet]) -> None:
|
|
|
50
50
|
|
|
51
51
|
|
|
52
52
|
def build_variable(
|
|
53
|
-
out: Path, light: Params = DISPLAY, middle_weight: float =
|
|
53
|
+
out: Path, light: Params = DISPLAY, middle_weight: float = 86, heavy_weight: float = 122
|
|
54
54
|
) -> Path:
|
|
55
55
|
masters = [light, replace(light, weight=heavy_weight)]
|
|
56
56
|
sets = [collect(p, draw=capsules) for p in masters]
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|