mirror of
https://github.com/belluzj/fantasque-sans.git
synced 2024-10-31 22:41:32 +01:00
Compare commits
16 Commits
Author | SHA1 | Date | |
---|---|---|---|
|
996150820b | ||
|
265d15ecae | ||
|
3fefa18b29 | ||
|
02917e46a1 | ||
|
6f32679e61 | ||
|
070726cfce | ||
|
a58e874526 | ||
|
5f00c7b95a | ||
|
d1c591af5a | ||
|
514454e9e7 | ||
|
290926b2da | ||
|
5c088fcf68 | ||
|
7506577e37 | ||
|
2508b90ce9 | ||
|
bb0e4dc3af | ||
|
824cd6a9f8 |
21
Dockerfile
Normal file
21
Dockerfile
Normal file
|
@ -0,0 +1,21 @@
|
||||||
|
FROM ubuntu:18.04
|
||||||
|
|
||||||
|
RUN apt-get update && \
|
||||||
|
apt-get install software-properties-common -y && \
|
||||||
|
add-apt-repository ppa:fontforge/fontforge -y && \
|
||||||
|
apt-get update && \
|
||||||
|
apt-get install -y --no-install-recommends \
|
||||||
|
fontforge \
|
||||||
|
woff-tools \
|
||||||
|
woff2 \
|
||||||
|
ttfautohint \
|
||||||
|
make \
|
||||||
|
zip
|
||||||
|
|
||||||
|
WORKDIR /fantasque
|
||||||
|
|
||||||
|
VOLUME /fantasque/Release
|
||||||
|
|
||||||
|
COPY . /fantasque
|
||||||
|
|
||||||
|
CMD ["make"]
|
13
README.md
13
README.md
|
@ -48,7 +48,7 @@ Stylistic set(s)
|
||||||
### `ss01`: nondescript `k`
|
### `ss01`: nondescript `k`
|
||||||
|
|
||||||
No ~~distractive~~ lovely loop.
|
No ~~distractive~~ lovely loop.
|
||||||
[Get the pre-activated version here](https://github.com/belluzj/fantasque-sans/releases/download/1.8.0/FantasqueSansMono-NoLoopK.zip)
|
[Get the pre-activated version here](https://github.com/belluzj/fantasque-sans/releases/download/v1.8.0/FantasqueSansMono-NoLoopK.zip)
|
||||||
or see the [issue #67](https://github.com/belluzj/fantasque-sans/issues/67)
|
or see the [issue #67](https://github.com/belluzj/fantasque-sans/issues/67)
|
||||||
for techniques to activate the stylistic set.
|
for techniques to activate the stylistic set.
|
||||||
|
|
||||||
|
@ -77,7 +77,7 @@ useful for users of accented capitals. For more info, see the [CHANGELOG](CHANGE
|
||||||
Automatic installation on macOS with [homebrew](https://brew.sh):
|
Automatic installation on macOS with [homebrew](https://brew.sh):
|
||||||
|
|
||||||
brew tap homebrew/cask-fonts #You only need to do this once for cask-fonts
|
brew tap homebrew/cask-fonts #You only need to do this once for cask-fonts
|
||||||
brew cask install font-fantasque-sans-mono
|
brew install --cask font-fantasque-sans-mono
|
||||||
|
|
||||||
Instructions for other platforms might follow.
|
Instructions for other platforms might follow.
|
||||||
|
|
||||||
|
@ -105,6 +105,15 @@ the latest prebuilt release of these fonts.
|
||||||
`make install` will install the TTF fonts into your local `.fonts/` directory
|
`make install` will install the TTF fonts into your local `.fonts/` directory
|
||||||
and update the font cache. It comes in handy while modifying the font.
|
and update the font cache. It comes in handy while modifying the font.
|
||||||
|
|
||||||
|
Alternatively, if you'd like to build Fantasque without installing required
|
||||||
|
dependencies, a Dockerfile is provided. Run the following command, and the
|
||||||
|
fonts will be built to the `./Variants` directory.
|
||||||
|
|
||||||
|
```sh
|
||||||
|
docker build -t fantasque .
|
||||||
|
docker run -v "$(pwd)/Variants:/fantasque/Variants" fantasque
|
||||||
|
```
|
||||||
|
|
||||||
[![](Specimen/Specimen.png)](Specimen/Specimen.pdf)
|
[![](Specimen/Specimen.png)](Specimen/Specimen.pdf)
|
||||||
|
|
||||||
Webfonts
|
Webfonts
|
||||||
|
|
|
@ -2,7 +2,10 @@
|
||||||
#
|
#
|
||||||
# Adapted from https://github.com/tonsky/FiraCode/blob/master/gen_calt.clj
|
# Adapted from https://github.com/tonsky/FiraCode/blob/master/gen_calt.clj
|
||||||
|
|
||||||
|
from __future__ import unicode_literals
|
||||||
|
|
||||||
from textwrap import dedent
|
from textwrap import dedent
|
||||||
|
from collections import defaultdict
|
||||||
import tempfile
|
import tempfile
|
||||||
|
|
||||||
|
|
||||||
|
@ -32,7 +35,7 @@ def update_features(font):
|
||||||
# Add the dummy "LIG" glyph
|
# Add the dummy "LIG" glyph
|
||||||
lig = font.createChar(-1, 'LIG')
|
lig = font.createChar(-1, 'LIG')
|
||||||
lig.width = font['space'].width
|
lig.width = font['space'].width
|
||||||
with tempfile.NamedTemporaryFile(suffix='.fea') as f:
|
with tempfile.NamedTemporaryFile(mode='w', suffix='.fea') as f:
|
||||||
f.write(fea_code)
|
f.write(fea_code)
|
||||||
f.seek(0)
|
f.seek(0)
|
||||||
font.mergeFeature(f.name)
|
font.mergeFeature(f.name)
|
||||||
|
@ -44,36 +47,192 @@ def rule(liga):
|
||||||
[LIG f i] LIG
|
[LIG f i] LIG
|
||||||
[ f f i] LIG }
|
[ f f i] LIG }
|
||||||
"""
|
"""
|
||||||
if len(liga) == 2:
|
rules = []
|
||||||
return dedent('''\
|
# standard ignores:
|
||||||
lookup {0}_{1} {{
|
# ignore sub {0} {0}' {1};
|
||||||
ignore sub {0} {0}' {1};
|
# ignore sub {0}' {1} {1};
|
||||||
ignore sub {0}' {1} {1};
|
if tuple(liga) not in skip_ignores:
|
||||||
sub {0}' {1} by LIG;
|
rules.extend(
|
||||||
sub LIG {1}' by {0}_{1}.liga;
|
[
|
||||||
}} {0}_{1};
|
ignore(prefix=liga[:1], head=liga[0], suffix=liga[1:]),
|
||||||
''').format(*liga)
|
ignore(head=liga[0], suffix=(liga[1:] + [liga[-1]])),
|
||||||
elif len(liga) == 3:
|
]
|
||||||
return dedent('''\
|
)
|
||||||
lookup {0}_{1}_{2} {{
|
|
||||||
ignore sub {0} {0}' {1} {2};
|
# careful with repeats:
|
||||||
ignore sub {0}' {1} {2} {2};
|
# #133 ->->->->, /**/**/**/, etc.
|
||||||
sub {0}' {1} {2} by LIG;
|
if len(liga) > 2 and liga[0] == liga[-1]:
|
||||||
sub LIG {1}' {2} by LIG;
|
rules.append(ignore([liga[-2]], liga[0], liga[1:]))
|
||||||
sub LIG LIG {2}' by {0}_{1}_{2}.liga;
|
rules.append(ignore(head=liga[0], suffix=(liga[1:] + [liga[1]])))
|
||||||
}} {0}_{1}_{2};
|
|
||||||
''').format(*liga)
|
# Don't cut into `prefix` to complete a ligature.
|
||||||
elif len(liga) == 4:
|
# i.e. regex `(?=`> is not `(?`=>.
|
||||||
return dedent('''\
|
rules.extend(
|
||||||
lookup {0}_{1}_{2}_{3} {{
|
[
|
||||||
ignore sub {0} {0}' {1} {2} {3};
|
ignore(prefix[:-n], liga[0], liga[1:])
|
||||||
ignore sub {0}' {1} {2} {3} {3};
|
for prefix in ignore_prefixes
|
||||||
sub {0}' {1} {2} {3} by LIG;
|
for n in range(1, len(liga))
|
||||||
sub LIG {1}' {2} {3} by LIG;
|
if prefix[-n:] == liga[:n]
|
||||||
sub LIG LIG {2}' {3} by LIG;
|
]
|
||||||
sub LIG LIG LIG {3}' by {0}_{1}_{2}_{3}.liga;
|
)
|
||||||
}} {0}_{1}_{2}_{3};
|
# hardcoded ignores, i.e. `<||>`
|
||||||
''').format(*liga)
|
rules.extend(ignores[tuple(liga)])
|
||||||
|
|
||||||
|
name = "_".join(liga)
|
||||||
|
# substitution logic
|
||||||
|
# sub {0}' {1} by LIG;
|
||||||
|
# sub LIG {1}' by {0}_{1}.liga;
|
||||||
|
for i in range(len(liga)):
|
||||||
|
init = _join(["LIG" for lig in liga[:i]])
|
||||||
|
tail = _join(liga[i + 1 :])
|
||||||
|
replace = "LIG" if (i + 1 < len(liga)) else (name + ".liga")
|
||||||
|
rules.append("sub{0} {1}'{2} by {3};".format(init, liga[i], tail, replace))
|
||||||
|
|
||||||
|
# put it all together
|
||||||
|
lines = (
|
||||||
|
["lookup " + name + " {"] + [" " + r for r in rules] + ["}} {0};".format(name)]
|
||||||
|
)
|
||||||
|
return "\n".join(lines)
|
||||||
|
|
||||||
|
|
||||||
|
def _join(items):
|
||||||
|
return (" " + " ".join(items)) if items else ""
|
||||||
|
|
||||||
|
|
||||||
|
def ignore(prefix=None, head=None, suffix=None):
|
||||||
|
""" don't substitute `head` if it's surrounded by `prefix` and `suffix` """
|
||||||
|
assert head
|
||||||
|
pref = _join(prefix)
|
||||||
|
rest = _join(suffix)
|
||||||
|
return "ignore sub{0} {1}'{2};".format(pref, head, rest)
|
||||||
|
|
||||||
|
|
||||||
|
ignores = defaultdict(
|
||||||
|
list,
|
||||||
|
{
|
||||||
|
("slash", "asterisk"): [
|
||||||
|
"ignore sub slash' asterisk slash;",
|
||||||
|
"ignore sub asterisk slash' asterisk;",
|
||||||
|
],
|
||||||
|
("asterisk", "slash"): [
|
||||||
|
"ignore sub slash asterisk' slash;",
|
||||||
|
"ignore sub asterisk' slash asterisk;",
|
||||||
|
],
|
||||||
|
# ("asterisk", "asterisk"): [
|
||||||
|
# "ignore sub slash asterisk' asterisk;",
|
||||||
|
# "ignore sub asterisk' asterisk slash;",
|
||||||
|
# ],
|
||||||
|
# ("asterisk", "asterisk", "asterisk"): [
|
||||||
|
# "ignore sub slash asterisk' asterisk asterisk;",
|
||||||
|
# "ignore sub asterisk' asterisk asterisk slash;",
|
||||||
|
# ],
|
||||||
|
# <||>
|
||||||
|
("less", "bar", "bar"): ["ignore sub less' bar bar greater;"],
|
||||||
|
("bar", "bar", "greater"): ["ignore sub less bar' bar greater;"],
|
||||||
|
# # :>=
|
||||||
|
# ("colon", "greater"): ["ignore sub colon' greater equal;"],
|
||||||
|
# # {|}
|
||||||
|
# ("braceleft", "bar"): ["ignore sub braceleft' bar braceright;"],
|
||||||
|
# ("bar", "braceright"): ["ignore sub braceleft bar' braceright;"],
|
||||||
|
# # [|]
|
||||||
|
# ("bracketleft", "bar"): ["ignore sub bracketleft' bar bracketright;"],
|
||||||
|
# ("bar", "bracketright"): ["ignore sub bracketleft bar' bracketright;"],
|
||||||
|
# # <*>>> <+>>> <$>>>
|
||||||
|
# ("greater", "greater", "greater"): [
|
||||||
|
# "ignore sub [asterisk plus dollar] greater' greater greater;"
|
||||||
|
# ],
|
||||||
|
# # <<<*> <<<+> <<<$>
|
||||||
|
# ("less", "less", "less"): ["ignore sub less' less less [asterisk plus dollar];"],
|
||||||
|
# # =:=
|
||||||
|
# ("colon", "equal"): ["ignore sub equal colon' equal;"],
|
||||||
|
# =!=
|
||||||
|
("exclam", "equal"): ["ignore sub equal exclam' equal;"],
|
||||||
|
# =!==
|
||||||
|
("exclam", "equal", "equal"): ["ignore sub equal exclam' equal equal;"],
|
||||||
|
# =<= <=< <=> <=| <=: <=! <=/
|
||||||
|
("less", "equal"): [
|
||||||
|
"ignore sub equal less' equal;",
|
||||||
|
"ignore sub less' equal [less greater bar colon exclam slash];",
|
||||||
|
],
|
||||||
|
# >=<
|
||||||
|
# =>= >=> >=< >=| >=: >=! >=/
|
||||||
|
("greater", "equal"): [
|
||||||
|
"ignore sub equal greater' equal;",
|
||||||
|
"ignore sub greater' equal [less greater bar colon exclam slash];",
|
||||||
|
],
|
||||||
|
# <*>> <+>> <$>>
|
||||||
|
# >>->> >>=>>
|
||||||
|
("greater", "greater"): [
|
||||||
|
# "ignore sub [asterisk plus dollar] greater' greater;",
|
||||||
|
# "ignore sub [hyphen equal] greater' greater;",
|
||||||
|
# "ignore sub greater' greater [hyphen equal];",
|
||||||
|
],
|
||||||
|
# <<*> <<+> <<$>
|
||||||
|
# <<-<< <<=<<
|
||||||
|
("less", "less"): [
|
||||||
|
# "ignore sub less' less [asterisk plus dollar];",
|
||||||
|
# "ignore sub [hyphen equal] less' less;",
|
||||||
|
# "ignore sub less' less [hyphen equal];",
|
||||||
|
],
|
||||||
|
# ||-|| ||=||
|
||||||
|
("bar", "bar"): [
|
||||||
|
"ignore sub [hyphen equal] bar' bar;",
|
||||||
|
"ignore sub bar' bar [hyphen equal];",
|
||||||
|
],
|
||||||
|
# # <--> >--< |--|
|
||||||
|
# ("hyphen", "hyphen"): [
|
||||||
|
# "ignore sub [less greater bar] hyphen' hyphen;",
|
||||||
|
# "ignore sub hyphen' hyphen [less greater bar];",
|
||||||
|
# ],
|
||||||
|
# # <---> >---< |---|
|
||||||
|
# ("hyphen", "hyphen", "hyphen"):
|
||||||
|
# "ignore sub [less greater bar] hyphen' hyphen hyphen;",
|
||||||
|
# "ignore sub hyphen' hyphen hyphen [less greater bar];",
|
||||||
|
# ],
|
||||||
|
("equal", "equal"): [ # ==
|
||||||
|
# "ignore sub bracketleft equal' equal;", # [==
|
||||||
|
# "ignore sub equal' equal bracketright;",# ==]
|
||||||
|
"ignore sub equal [colon exclam] equal' equal;", # =:== =!==
|
||||||
|
# "ignore sub [less greater bar slash] equal' equal;", # <== >== |== /==
|
||||||
|
# "ignore sub equal' equal [less greater bar slash];", # ==< ==> ==| ==/
|
||||||
|
"ignore sub equal' equal [colon exclam] equal;", # ==:= ==!=
|
||||||
|
],
|
||||||
|
# [===[ ]===]
|
||||||
|
# [=== ===]
|
||||||
|
# <===> >===< |===| /===/ =:=== =!=== ===:= ===!=
|
||||||
|
("equal", "equal", "equal"): [
|
||||||
|
# "ignore sub bracketleft equal' equal equal;",
|
||||||
|
# "ignore sub equal' equal equal bracketright;",
|
||||||
|
"ignore sub equal [colon exclam] equal' equal equal;",
|
||||||
|
"ignore sub [less greater bar slash] equal' equal equal;",
|
||||||
|
# "ignore sub equal' equal equal [less greater bar slash];",
|
||||||
|
"ignore sub equal' equal equal [colon exclam] equal;",
|
||||||
|
],
|
||||||
|
# #118 https://
|
||||||
|
("slash", "slash"): ["ignore sub colon slash' slash;"],
|
||||||
|
},
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
ignore_prefixes = [
|
||||||
|
["parenleft", "question", "colon"],
|
||||||
|
# Regexp lookahead/lookbehind
|
||||||
|
["parenleft", "question", "equal"],
|
||||||
|
["parenleft", "question", "less", "equal"],
|
||||||
|
["parenleft", "question", "exclam"],
|
||||||
|
["parenleft", "question", "less", "exclam"],
|
||||||
|
# PHP <?=
|
||||||
|
["less", "question", "equal"],
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
|
# DO NOT generate ignores at all
|
||||||
|
skip_ignores = {
|
||||||
|
# # <<*>> <<+>> <<$>>
|
||||||
|
# ("less", "asterisk", "greater"),
|
||||||
|
# ("less", "plus", "greater"),
|
||||||
|
# ("less", "dollar", "greater"),
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
def indent(text, prefix):
|
def indent(text, prefix):
|
||||||
|
|
|
@ -3,6 +3,8 @@
|
||||||
# LICENSE: MIT
|
# LICENSE: MIT
|
||||||
# vim: sts=4 sw=4 ts=4 et
|
# vim: sts=4 sw=4 ts=4 et
|
||||||
|
|
||||||
|
from past.builtins import xrange
|
||||||
|
|
||||||
import fontforge
|
import fontforge
|
||||||
from itertools import compress
|
from itertools import compress
|
||||||
import os
|
import os
|
||||||
|
|
Loading…
Reference in New Issue
Block a user