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