rn
[llpp.git] / misc / llppac
blob31cdc8cc043c6d4cddc6bde5fa39e0f0c5c6ef69
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 <i>Nürnberg</i> (rn -> m)
51 Apay Арау
52 örök für
53 - - (~-) ~ ~ (-~)
54 curly vs plain braces {} () {} →
55 Bjarne Stroustrup (/ˈbjɑːrnə ˈstraʊstrʊp/; Danish: [ˈbjɑːnə ˈsdʁʌwˀsdʁɔb]
57 kerning
58 echo \${@:5}
59 life [l i fe]
60 lambdabot [l a mb]
61 Commutative [Co mm utative]
62 weird [we i rd]
63 Before [Bef ore, Be for e]
64 higher [gh, h i gher, hi gher]
65 multi [mu lti]
66 till [ti ll]
67 language [an]
68 plan [la]
69 when [wh]
70 kerning [rn | ng]
71 мне [мн е]
72 oiled [oi led]
73 mkfifo [mk f i fo, mk f i fo]
74 didn't [di dn't]
75 argumnet (sic) []
76 more [mo re]
77 CmmCall [CmmC a l l]
78 -Wvla [-Wv la]
79 align [a l i gn]
80 Compiling [Co mp iling]
81 print [pr int]
82 fcmono [f cmono]
83 Mail [M ail]
84 xsrc [x src]
85 Pokorna
86 buildglyphs.js [buil dg lyphs]
87 Dollar [Do ll ar]
88 signed [s i gned]
89 Pine [Pi ne]
90 right [r i ght]
91 ugliness
92 Nigeria [Ni g eria]
93 Nothing [Nothi ng]
94 modify [mo dify]
95 mplus [mp lus]
96 Apostolic [A postolic]
97 коде [к о де]
98 Прокофьевну [Пра ко фьевну]
99 Хэлп [X элп]
100 коснулся [ко снулся]
101 обьявляным [об ья вленым]
102 Queen [Qu een]
103 etymological [et ymologoical]
104 sigh [s i gh]
105 git [gi t]
106 некочевого [не ко чевого]
107 Розовое [Ро зо вое]
108 Trump [Tru mp]
109 покрытие [по кр ытие]
110 Julia [J ulia | Jul i a]
112 almost kerning
113 hope doesn't
114 Illegal
115 automatically effective
116 Ilium is the Latin for Ilion.
118 (from UTF8-demo.txt)
119 Box drawing alignment tests: █
121 ╔══╦══╗ ┌──┬──┐ ╭──┬──╮ ╭──┬──╮ ┏━━┳━━┓ ┎┒┏┑ ╷ ╻ ┏┯┓ ┌┰┐ ▊ ╱╲╱╲╳╳╳
122 ║┌─╨─┐║ │╔═╧═╗│ │╒═╪═╕│ │╓─╁─╖│ ┃┌─╂─┐┃ ┗╃╄┙ ╶┼╴╺╋╸┠┼┨ ┝╋┥ ▋ ╲╱╲╱╳╳╳
123 ║│╲ ╱│║ │║ ║│ ││ │ ││ │║ ┃ ║│ ┃│ ╿ │┃ ┍╅╆┓ ╵ ╹ ┗┷┛ └┸┘ ▌ ╱╲╱╲╳╳╳
124 ╠╡ ╳ ╞╣ ├╢ ╟┤ ├┼─┼─┼┤ ├╫─╂─╫┤ ┣┿╾┼╼┿┫ ┕┛┖┚ ┌┄┄┐ ╎ ┏┅┅┓ ┋ ▍ ╲╱╲╱╳╳╳
125 ║│╱ ╲│║ │║ ║│ ││ │ ││ │║ ┃ ║│ ┃│ ╽ │┃ ░░▒▒▓▓██ ┊ ┆ ╎ ╏ ┇ ┋ ▎
126 ║└─╥─┘║ │╚═╤═╝│ │╘═╪═╛│ │╙─╀─╜│ ┃└─╂─┘┃ ░░▒▒▓▓██ ┊ ┆ ╎ ╏ ┇ ┋ ▏
127 ╚══╩══╝ └──┴──┘ ╰──┴──╯ ╰──┴──╯ ┗━━┻━━┛ ▗▄▖▛▀▜ └╌╌┘ ╎ ┗╍╍┛ ┋ ▁▂▃▄▅▆▇█
128 ▝▀▘▙▄▟
130 https://mirrors.zju.edu.cn/CTAN/fonts/gofonts/doc/gofonts.pdf (page 2)
132 DIN Legibility Standard
134 The recent German DIN 1450 legibility standard
135 recommends several features for font legibility, including
136 differentiation of letter shapes to reduce confusion. The Go fonts
137 conform to the 1450 standard by carefully differentiating zero from
138 capital O; numeral 1 from capital I (eye) and lowercase l (ell);
139 numeral 5 from capital S; and numeral 8 from capital B. The shapes of
140 bowls of b d p q follow the natural asymmetries of legible Renaissance
141 handwriting, aiding differentiation to reduce confusion. [5]
144 Mistaking S for a 5 (at certain sizes) is more of a problem... but... Ze Germans
146 (https://en.wikipedia.org/wiki/Jabberwocky
147 Idea from the aforementioned gofonts paper)
149 Бе сгладне и честлинните комбурси Það leið að stekju, og slýgir greðlar
150 търляха се и сврецваха във плите; sig snældu og böluðu um slöffruna,
151 съвсем окласни бяха тук щурпите og angurvært sungu sópfiðrungar
152 и отма равапсатваха прасурси. við sífgelt týðmana svíræna.
154 (https://en.wikipedia.org/wiki/Typeface)
156 For the rational mind, type design can be a maddening game
157 of drawing things differently in order to make them appear the
158 same.
159 </pre>
163 maketext() {
164 # https://github.com/react-boilerplate/react-boilerplate/issues/1340
165 test -d "$cachedir/fonts" || mkdir "$cachedir/fonts"
166 filename="$(basename "$1")"
167 textfilename="$2"
168 cat >"$cachedir/fonts/text.html" <<EOF
169 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
170 "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
171 <html>
172 <head>
173 <meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
174 <title>$filename</title>
175 <style type="text/css">
176 @font-face { font-family: moo; src: url('$1'); }
177 pre { font-family: moo; }
178 </style>
179 </head>
180 $filename
181 <body>
183 for size in 6 8 10 12 4 2; do
184 text $size $textfilename >>"$cachedir/fonts/text.html"
185 done
186 cat >>"$cachedir/fonts/text.html" <<EOF
187 <br/>
188 $(fc-scan -f '%{fullname} %{style} %{slant} %{file} %{fontversion} %{capability} %{lang}' "$1" || file "$1")
189 </body>
190 </html>
194 trap 'test -n "$casp" && rm -f "$casp"' 0
196 while getopts s:c:m:t:fu opt; do
197 case $opt in
198 m) mime=$OPTARG;;
199 t) type=$OPTARG;;
200 f) force=true;;
201 c) css="-s $OPTARG";;
202 s) textfilename="$OPTARG";;
203 ?) die "usage: $0 [-c css] [-m mime/type] [-t filter] [-f] [-s textfile] [path|url]";;
204 esac
205 done
206 shift $(($OPTIND - 1))
207 test -z "$1" && die "usage $0: path"
209 origin="$1"
210 if ${force-test ! -e "$1"} && expr >/dev/null "$1" : "\(ftp\|https\?\)://"; then
211 if executable_p wget; then
212 dl() { wget -q $1 -O $2; }
213 elif executable_p curl; then
214 dl() { curl -L $1 -o $2; }
215 else
216 die "no program to fetch remote urls found"
219 hashof="$cachedir/$(basename "$1")"
220 dl "$1" "$hashof" || test -e "$md5of"
221 shift
222 set -- "$hashof" "$@"
223 else
224 hashof="$1"
227 test -z "$type" && { ft=$(file -L --mime-type -b "$1") || die "$ft"; }
229 case $ft in
230 application/x-gzip | application/x-compress) dc=zcat;;
231 application/x-xz) dc=xzcat;;
232 application/x-bzip2) dc=bzcat;;
233 *) unset dc || true;;
234 esac
236 filt='"${dc-cat}" "$1" |'
238 typeofmime() {
239 case "$1" in
240 application/postscript) type=ps;;
241 application/pdf) type=pdf;;
242 image/vnd.djvu) type=djvu;;
243 text/html) type=html;;
244 text/plain) type=text;;
245 application/msword) type=word;;
246 application/vnd.openxmlformats-officedocument.* \
247 | application/vnd.ms-powerpoint \
248 | application/vnd.ms-excel \
249 | application/vnd.oasis.opendocument.*) type=uno;;
250 image/svg+xml) type=svg;;
251 image/png | image/jpeg) test -n "$dc" && type="image" || type="image2";;
252 image/*) type=image;;
253 application/x-dvi) type=dvi;;
254 application/x-font-ttf \
255 | application/vnd.ms-opentype \
256 | application/font-sfnt) type=font;;
257 *) return 1;;
258 esac
259 return 0
262 if test -z "$type"; then
263 test -z "$mime" && \
264 mime=$(file -L --mime-type -b "$1" || die "$mime") || \
265 $(file -L --mime-type -bz "$1" || die "$mime")
266 typeofmime "$mime" || die "unhandled file type: '$mime'"
269 caspsuf=".pdf"
270 case $type in
271 ps) conv='ps2pdf - "$casp"';;
272 image2|pdf) test -z "$dc" && exec llpp "$@" || conv='cat >"$casp"';;
273 texi) {
274 missing texi2html "texi2html(http://www.nongnu.org/texi2html/)"
275 missing prince "PrinceXML(http://www.princexml.com/)"
276 conv='texi2html - -o - | prince $css - -o "$casp"'
278 djvu) {
279 missing ddjvu "ddjvu(http://djvu.sourceforge.net/doc/man/ddjvu.html)"
280 conv='ddjvu -format=pdf - "$casp"'
282 html) {
283 missing prince "Prince(http://www.princexml.com/)"
284 conv='prince $css - -o "$casp"'
286 html2epub) {
287 missing pandoc "pandoc(http://pandoc.org)"
288 caspsuf=".epub"
289 conv='pandoc -r html - -w epub2 -o "$casp"'
291 word) {
292 if executable_p unoconv && test -z "$dc"; then
293 unset filt
294 conv='unoconv -o "$casp" "$1"'
295 else
296 missing antiword "antiword or unoconv"
297 conv='antiword -m 8859-1.txt -a a4 - >"$casp"'
300 uno) {
301 test -n "$dc" && die "cannot convert compressed '$mime'"
302 unset filt
303 missing unoconv "unoconv(http://dag.wiee.rs/home-made/unoconv/)"
304 conv='unoconv -o "$casp" "$1"'
306 svg) {
307 if executable_p inkscape && test -z "$dc"; then
308 unset filt
309 conv='inkscape -z -A "$casp" "$1"'
310 else
311 missing rsvg-convert "rsvg-convert"
312 conv='rsvg-convert -f pdf -o "$casp"'
315 font) {
316 maketext "$1" "$textfilename"
317 exec llpp -origin $1 -layout-height 0 "$cachedir/fonts/text.html"
319 image) {
320 missing convert "convert(http://www.imagemagick.org/script/convert.php)"
321 conv='convert - pdf:"$casp"'
323 dvi) {
324 test -n "$dc" && die "cannot convert compressed '$mime'"
325 unset filt
326 missing dvipdf "dvipdf(http://ghostscript.com/)"
327 conv='dvipdf "$1" "$casp"'
329 text) {
330 missing pandoc "pandoc(http://pandoc.org/)"
331 conv='pandoc -t epub2 - -o "$casp"'
332 caspsuf=.epub
334 *) die "unhandled filter type: '$type'";;
335 esac
337 hash=$(cksum "$hashof") || die "$hash"
338 casp=$cachedir/${hash%% *}$caspsuf
340 { test -n "$force" || test ! -e "$casp"; } && eval "$filt" "$conv"
341 shift
343 exec llpp -origin $origin "$@" "$casp"