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