More kerning
[llpp.git] / misc / llppac
blobf3d85c3ea92a2fbbd50fdbc83277745beb736409
1 #!/bin/sh
2 set -e
4 die() {
5 echo "$1" >&2
6 exit 1
9 cachedir="${XDG_CACHE_HOME:-$HOME/.cache}/llpp"
10 test -d "$cachedir" || die "cache directory '$cachedir' does not exist"
12 caspsuf=
13 type=
15 executable_p() { command -v "$1" >/dev/null 2>&1; }
17 missing() {
18 executable_p $1 || \
19 eval "$1() { die \"$2 is needed for \$type conversion\"; }"
22 text() {
23 cat <<EOF
24 <pre style="font-size: ${1}pt;">
25 === $1 ===
26 EOF
27 test -n "$2" && cat $2 || cat <<EOF
28 S9 З3Ӡʒ Il1
30 ЁЖЗ
32 abcdefghijklmnopqrstwxyz
33 ABCDEFGHIJKLMNOPQRSTWXYZ
34 абвгдеёжзийклмнопрстуфхцчшщэюя
35 АБВГДЕЁЖЗИЙКЛМНОПРСТУФХЦЧШЩЭЮЯ
36 инпипнишпнипшнипнпншпнпинпипнпипщнпипипин
37 иннициатива шиорокошарикоподшипниковый взбзднуть гидроаэроионизация
38 телегаммааппарат фельдъегерь четырёхсотпятидесятисемимиллиметровое
39 превысокомногорассмотрительствующий вскользь забулдыжничество
40 цецецница
41 Σομε πσθδο γρεεκ
42 \`1234567890-=\\
43 ~!@#\$$%^&*()_+|
44 [];',./
45 {}:"&lt;&gt;?"
46 S in S9 59 S9 is like 5
47 final fjord flair ft
48 3ЗЭэзээз3ЗqgO0o ijklI1| bgqpykvwlliliiijil1 lLLl
49 01234567890 3ДС ЗДС ӠДС ʒДС
50 rnrmnnmrrrnmmr
51 Apay Арау
52 örök für
53 - - (~-) ~ ~ (-~)
54 curly vs plain braces {} () {} →
56 kerning
57 echo \${@:5}
58 life [l i fe]
59 lambdabot [l a mb]
60 Commutative [Co mm utative]
61 weird [we i rd]
62 Before [Bef ore, Be for e]
63 higher [gh, h i gher, hi gher]
64 multi [mu lti]
65 till [ti ll]
66 language [an]
67 plan [la]
68 when [wh]
69 kerning [rn | ng]
70 мне [мн е]
71 oiled [oi led]
72 mkfifo [mk f i fo, mk f i fo]
73 didn't [di dn't]
74 argumnet (sic) []
75 more [mo re]
76 CmmCall [CmmC a l l]
77 -Wvla [-Wv la]
78 align [a l i gn]
79 Compiling [Co mp iling]
80 print [pr int]
81 fcmono [f cmono]
82 Mail [M ail]
83 xsrc [x src]
84 Pokorna
85 buildglyphs.js [buil dg lyphs]
86 Dollar [Do ll ar]
87 signed [s i gned]
88 Pine [Pi ne]
89 right [r i ght]
90 ugliness
91 Nigeria [Ni g eria]
92 Nothing [Nothi ng]
93 modify [mo dify]
94 mplus [mp lus]
95 Apostolic [A postolic]
96 коде [к о де]
97 Прокофьевну [Пра ко фьевну]
98 Хэлп [X элп]
99 коснулся [ко снулся]
100 обьявляным [об ья вленым]
101 Queen [Qu een]
102 etymological [et ymologoical]
103 sigh [s i gh]
104 git [gi t]
105 некочевого [не ко чевого]
106 Розовое [Ро зо вое]
108 almost kerning
109 hope doesn't
110 Illegal
111 automatically effective
112 Ilium is the Latin for Ilion.
114 (from UTF8-demo.txt)
115 Box drawing alignment tests: █
117 ╔══╦══╗ ┌──┬──┐ ╭──┬──╮ ╭──┬──╮ ┏━━┳━━┓ ┎┒┏┑ ╷ ╻ ┏┯┓ ┌┰┐ ▊ ╱╲╱╲╳╳╳
118 ║┌─╨─┐║ │╔═╧═╗│ │╒═╪═╕│ │╓─╁─╖│ ┃┌─╂─┐┃ ┗╃╄┙ ╶┼╴╺╋╸┠┼┨ ┝╋┥ ▋ ╲╱╲╱╳╳╳
119 ║│╲ ╱│║ │║ ║│ ││ │ ││ │║ ┃ ║│ ┃│ ╿ │┃ ┍╅╆┓ ╵ ╹ ┗┷┛ └┸┘ ▌ ╱╲╱╲╳╳╳
120 ╠╡ ╳ ╞╣ ├╢ ╟┤ ├┼─┼─┼┤ ├╫─╂─╫┤ ┣┿╾┼╼┿┫ ┕┛┖┚ ┌┄┄┐ ╎ ┏┅┅┓ ┋ ▍ ╲╱╲╱╳╳╳
121 ║│╱ ╲│║ │║ ║│ ││ │ ││ │║ ┃ ║│ ┃│ ╽ │┃ ░░▒▒▓▓██ ┊ ┆ ╎ ╏ ┇ ┋ ▎
122 ║└─╥─┘║ │╚═╤═╝│ │╘═╪═╛│ │╙─╀─╜│ ┃└─╂─┘┃ ░░▒▒▓▓██ ┊ ┆ ╎ ╏ ┇ ┋ ▏
123 ╚══╩══╝ └──┴──┘ ╰──┴──╯ ╰──┴──╯ ┗━━┻━━┛ ▗▄▖▛▀▜ └╌╌┘ ╎ ┗╍╍┛ ┋ ▁▂▃▄▅▆▇█
124 ▝▀▘▙▄▟
126 https://mirrors.zju.edu.cn/CTAN/fonts/gofonts/doc/gofonts.pdf (page 2)
128 DIN Legibility Standard
130 The recent German DIN 1450 legibility standard
131 recommends several features for font legibility, including
132 differentiation of letter shapes to reduce confusion. The Go fonts
133 conform to the 1450 standard by carefully differentiating zero from
134 capital O; numeral 1 from capital I (eye) and lowercase l (ell);
135 numeral 5 from capital S; and numeral 8 from capital B. The shapes of
136 bowls of b d p q follow the natural asymmetries of legible Renaissance
137 handwriting, aiding differentiation to reduce confusion. [5]
140 Mistaking S for a 5 (at certain sizes) is more of a problem... but... Ze Germans
142 (https://en.wikipedia.org/wiki/Jabberwocky
143 Idea from the aforementioned gofonts paper)
145 Бе сгладне и честлинните комбурси Það leið að stekju, og slýgir greðlar
146 търляха се и сврецваха във плите; sig snældu og böluðu um slöffruna,
147 съвсем окласни бяха тук щурпите og angurvært sungu sópfiðrungar
148 и отма равапсатваха прасурси. við sífgelt týðmana svíræna.
150 (https://en.wikipedia.org/wiki/Typeface)
152 For the rational mind, type design can be a maddening game
153 of drawing things differently in order to make them appear the
154 same.
155 </pre>
159 maketext() {
160 # https://github.com/react-boilerplate/react-boilerplate/issues/1340
161 test -d "$cachedir/fonts" || mkdir "$cachedir/fonts"
162 filename="$(basename "$1")"
163 textfilename="$2"
164 cat >"$cachedir/fonts/text.html" <<EOF
165 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
166 "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
167 <html>
168 <head>
169 <meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
170 <title>$filename</title>
171 <style type="text/css">
172 @font-face { font-family: moo; src: url('$1'); }
173 pre { font-family: moo; }
174 </style>
175 </head>
176 $filename
177 <body>
179 for size in 6 8 10 12 4 2; do
180 text $size $textfilename >>"$cachedir/fonts/text.html"
181 done
182 cat >>"$cachedir/fonts/text.html" <<EOF
183 <br/>
184 $(fc-scan -f '%{fullname} %{style} %{slant} %{file} %{fontversion} %{capability} %{lang}' "$1" || file "$1")
185 </body>
186 </html>
190 trap 'test -n "$casp" && rm -f "$casp"' 0
192 while getopts s:c:m:t:fu opt; do
193 case $opt in
194 m) mime=$OPTARG;;
195 t) type=$OPTARG;;
196 f) force=true;;
197 c) css="-s $OPTARG";;
198 s) textfilename="$OPTARG";;
199 ?) die "usage: $0 [-c css] [-m mime/type] [-t filter] [-f] [-s textfile] [path|url]";;
200 esac
201 done
202 shift $(($OPTIND - 1))
203 test -z "$1" && die "usage $0: path"
205 origin="$1"
206 if ${force-test ! -e "$1"} && expr >/dev/null "$1" : "\(ftp\|https\?\)://"; then
207 if executable_p wget; then
208 dl() { wget -q $1 -O $2; }
209 elif executable_p curl; then
210 dl() { curl -L $1 -o $2; }
211 else
212 die "no program to fetch remote urls found"
215 hashof="$cachedir/$(basename "$1")"
216 dl "$1" "$hashof" || test -e "$md5of"
217 shift
218 set -- "$hashof" "$@"
219 else
220 hashof="$1"
223 test -z "$type" && { ft=$(file -L --mime-type -b "$1") || die "$ft"; }
225 case $ft in
226 application/x-gzip | application/x-compress) dc=zcat;;
227 application/x-xz) dc=xzcat;;
228 application/x-bzip2) dc=bzcat;;
229 *) unset dc || true;;
230 esac
232 filt='"${dc-cat}" "$1" |'
234 typeofmime() {
235 case "$1" in
236 application/postscript) type=ps;;
237 application/pdf) type=pdf;;
238 image/vnd.djvu) type=djvu;;
239 text/html) type=html;;
240 text/plain) type=text;;
241 application/msword) type=word;;
242 application/vnd.openxmlformats-officedocument.* \
243 | application/vnd.ms-powerpoint \
244 | application/vnd.ms-excel \
245 | application/vnd.oasis.opendocument.*) type=uno;;
246 image/svg+xml) type=svg;;
247 image/png | image/jpeg) test -n "$dc" && type="image" || type="image2";;
248 image/*) type=image;;
249 application/x-dvi) type=dvi;;
250 application/x-font-ttf \
251 | application/vnd.ms-opentype \
252 | application/font-sfnt) type=font;;
253 *) return 1;;
254 esac
255 return 0
258 if test -z "$type"; then
259 test -z "$mime" && \
260 mime=$(file -L --mime-type -b "$1" || die "$mime") || \
261 $(file -L --mime-type -bz "$1" || die "$mime")
262 typeofmime "$mime" || die "unhandled file type: '$mime'"
265 caspsuf=".pdf"
266 case $type in
267 ps) conv='ps2pdf - "$casp"';;
268 image2|pdf) test -z "$dc" && exec llpp "$@" || conv='cat >"$casp"';;
269 texi) {
270 missing texi2html "texi2html(http://www.nongnu.org/texi2html/)"
271 missing prince "PrinceXML(http://www.princexml.com/)"
272 conv='texi2html - -o - | prince $css - -o "$casp"'
274 djvu) {
275 missing ddjvu "ddjvu(http://djvu.sourceforge.net/doc/man/ddjvu.html)"
276 conv='ddjvu -format=pdf - "$casp"'
278 html) {
279 missing prince "Prince(http://www.princexml.com/)"
280 conv='prince $css - -o "$casp"'
282 html2epub) {
283 missing pandoc "pandoc(http://pandoc.org)"
284 caspsuf=".epub"
285 conv='pandoc -r html - -w epub2 -o "$casp"'
287 word) {
288 if executable_p unoconv && test -z "$dc"; then
289 unset filt
290 conv='unoconv -o "$casp" "$1"'
291 else
292 missing antiword "antiword or unoconv"
293 conv='antiword -m 8859-1.txt -a a4 - >"$casp"'
296 uno) {
297 test -n "$dc" && die "cannot convert compressed '$mime'"
298 unset filt
299 missing unoconv "unoconv(http://dag.wiee.rs/home-made/unoconv/)"
300 conv='unoconv -o "$casp" "$1"'
302 svg) {
303 if executable_p inkscape && test -z "$dc"; then
304 unset filt
305 conv='inkscape -z -A "$casp" "$1"'
306 else
307 missing rsvg-convert "rsvg-convert"
308 conv='rsvg-convert -f pdf -o "$casp"'
311 font) {
312 maketext "$1" "$textfilename"
313 exec llpp -origin $1 -layout-height 0 "$cachedir/fonts/text.html"
315 image) {
316 missing convert "convert(http://www.imagemagick.org/script/convert.php)"
317 conv='convert - pdf:"$casp"'
319 dvi) {
320 test -n "$dc" && die "cannot convert compressed '$mime'"
321 unset filt
322 missing dvipdf "dvipdf(http://ghostscript.com/)"
323 conv='dvipdf "$1" "$casp"'
325 text) {
326 missing pandoc "pandoc(http://pandoc.org/)"
327 conv='pandoc -t epub2 - -o "$casp"'
328 caspsuf=.epub
330 *) die "unhandled filter type: '$type'";;
331 esac
333 hash=$(cksum "$hashof") || die "$hash"
334 casp=$cachedir/${hash%% *}$caspsuf
336 { test -n "$force" || test ! -e "$casp"; } && eval "$filt" "$conv"
337 shift
339 exec llpp -origin $origin "$@" "$casp"