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