author | wenzelm |
Thu, 29 Nov 2018 14:43:11 +0100 | |
changeset 69372 | 69de0f561824 |
parent 69371 | 3539767d5c61 |
child 69373 | 2c0af1c2e723 |
permissions | -rw-r--r-- |
69339 | 1 |
/* Title: Pure/Admin/build_fonts.scala |
69330 | 2 |
Author: Makarius |
3 |
||
69354 | 4 |
Build standard Isabelle fonts: DejaVu base + Isabelle symbols. |
69330 | 5 |
*/ |
6 |
||
7 |
package isabelle |
|
8 |
||
9 |
||
69339 | 10 |
object Build_Fonts |
69330 | 11 |
{ |
12 |
/* relevant codepoint ranges */ |
|
13 |
||
14 |
object Range |
|
15 |
{ |
|
69336 | 16 |
def base_font: Seq[Int] = |
69330 | 17 |
(0x0020 to 0x007e) ++ // ASCII |
18 |
(0x00a0 to 0x024f) ++ // Latin Extended-A/B |
|
19 |
(0x0400 to 0x04ff) ++ // Cyrillic |
|
20 |
(0x0600 to 0x06ff) ++ // Arabic |
|
21 |
Seq( |
|
22 |
0x2018, // single quote |
|
23 |
0x2019, // single quote |
|
24 |
0x201a, // single quote |
|
25 |
0x201c, // double quote |
|
26 |
0x201d, // double quote |
|
27 |
0x201e, // double quote |
|
28 |
0x2039, // single guillemet |
|
29 |
0x203a, // single guillemet |
|
69331 | 30 |
0x204b, // FOOTNOTE |
69330 | 31 |
0x20ac, // Euro |
32 |
0xfb01, // ligature fi |
|
33 |
0xfb02, // ligature fl |
|
34 |
0xfffd, // replacement character |
|
35 |
) |
|
36 |
||
69336 | 37 |
def isabelle_font: Seq[Int] = |
69330 | 38 |
Seq( |
39 |
0x05, // X |
|
40 |
0x06, // Y |
|
41 |
0x07, // EOF |
|
42 |
0x7f, // DEL |
|
69341
6aa24ccd8049
proper superscript "-1", based on "Deja Vu Sans Condensed" U+207b/U+00b9, with bold version via "Change Weight / Embolden by 80 em units";
wenzelm
parents:
69339
diff
changeset
|
43 |
0xaf, // INVERSE |
69330 | 44 |
0xac, // logicalnot |
45 |
0xb0, // degree |
|
46 |
0xb1, // plusminus |
|
47 |
0xb7, // periodcentered |
|
48 |
0xd7, // multiply |
|
49 |
0xf7, // divide |
|
50 |
) ++ |
|
51 |
(0x0370 to 0x03ff) ++ // Greek (pseudo math) |
|
69336 | 52 |
(0x0590 to 0x05ff) ++ // Hebrew (non-mono) |
69330 | 53 |
Seq( |
54 |
0x2010, // hyphen |
|
55 |
0x2013, // dash |
|
56 |
0x2014, // dash |
|
57 |
0x2015, // dash |
|
58 |
0x2020, // dagger |
|
59 |
0x2021, // double dagger |
|
60 |
0x2022, // bullet |
|
61 |
0x2026, // ellipsis |
|
62 |
0x2030, // perthousand |
|
63 |
0x2032, // minute |
|
64 |
0x2033, // second |
|
65 |
0x2038, // caret |
|
66 |
0x20cd, // currency symbol |
|
67 |
) ++ |
|
68 |
(0x2100 to 0x214f) ++ // Letterlike Symbols |
|
69 |
(0x2190 to 0x21ff) ++ // Arrows |
|
70 |
(0x2200 to 0x22ff) ++ // Mathematical Operators |
|
71 |
(0x2300 to 0x23ff) ++ // Miscellaneous Technical |
|
72 |
Seq( |
|
73 |
0x2423, // graphic for space |
|
74 |
0x2500, // box drawing |
|
75 |
0x2501, // box drawing |
|
76 |
0x2508, // box drawing |
|
77 |
0x2509, // box drawing |
|
78 |
0x2550, // box drawing |
|
79 |
) ++ |
|
80 |
(0x25a0 to 0x25ff) ++ // Geometric Shapes |
|
81 |
Seq( |
|
69331 | 82 |
0x261b, // ACTION |
69330 | 83 |
0x2660, // spade suit |
84 |
0x2661, // heart suit |
|
85 |
0x2662, // diamond suit |
|
86 |
0x2663, // club suit |
|
87 |
0x266d, // musical flat |
|
88 |
0x266e, // musical natural |
|
89 |
0x266f, // musical sharp |
|
90 |
0x2756, // UNDEFINED |
|
91 |
0x2759, // BOLD |
|
92 |
0x27a7, // DESCR |
|
93 |
0x27e6, // left white square bracket |
|
94 |
0x27e7, // right white square bracket |
|
95 |
0x27e8, // left angle bracket |
|
96 |
0x27e9, // right angle bracket |
|
97 |
) ++ |
|
98 |
(0x27f0 to 0x27ff) ++ // Supplemental Arrows-A |
|
99 |
(0x2900 to 0x297f) ++ // Supplemental Arrows-B |
|
100 |
(0x2980 to 0x29ff) ++ // Miscellaneous Mathematical Symbols-B |
|
101 |
(0x2a00 to 0x2aff) ++ // Supplemental Mathematical Operators |
|
102 |
Seq(0x2b1a) ++ // VERBATIM |
|
103 |
(0x1d400 to 0x1d7ff) ++ // Mathematical Alphanumeric Symbols |
|
104 |
Seq( |
|
69331 | 105 |
0x1f310, // globe with meridians (Symbola font) |
106 |
0x1f4d3, // notebook (Symbola font) |
|
107 |
0x1f5c0, // folder (Symbola font) |
|
108 |
0x1f5cf, // page (Symbola font) |
|
69330 | 109 |
) |
69371
3539767d5c61
generate Vacuous font from domain of Isabelle fonts;
wenzelm
parents:
69354
diff
changeset
|
110 |
|
3539767d5c61
generate Vacuous font from domain of Isabelle fonts;
wenzelm
parents:
69354
diff
changeset
|
111 |
val vacuous_font: Seq[Int] = |
3539767d5c61
generate Vacuous font from domain of Isabelle fonts;
wenzelm
parents:
69354
diff
changeset
|
112 |
Seq(0x3c) // "<" as template |
69330 | 113 |
} |
114 |
||
115 |
||
116 |
/* font families */ |
|
117 |
||
69332 | 118 |
sealed case class Family( |
119 |
plain: String = "", |
|
120 |
bold: String = "", |
|
121 |
italic: String = "", |
|
69336 | 122 |
bold_italic: String = "") |
123 |
{ |
|
124 |
val fonts: List[String] = |
|
125 |
proper_string(plain).toList ::: |
|
126 |
proper_string(bold).toList ::: |
|
127 |
proper_string(italic).toList ::: |
|
128 |
proper_string(bold_italic).toList |
|
129 |
||
130 |
def get(index: Int): String = fonts(index % fonts.length) |
|
131 |
} |
|
69330 | 132 |
|
133 |
object Family |
|
134 |
{ |
|
69336 | 135 |
def isabelle_text: Family = |
136 |
Family( |
|
137 |
plain = "IsabelleText.sfd", |
|
138 |
bold = "IsabelleTextBold.sfd") |
|
139 |
||
69332 | 140 |
def deja_vu_sans_mono: Family = |
69330 | 141 |
Family( |
69332 | 142 |
plain = "DejaVuSansMono.ttf", |
143 |
bold = "DejaVuSansMono-Bold.ttf", |
|
144 |
italic = "DejaVuSansMono-Oblique.ttf", |
|
69336 | 145 |
bold_italic = "DejaVuSansMono-BoldOblique.ttf") |
69330 | 146 |
|
69332 | 147 |
def deja_vu_sans: Family = |
69330 | 148 |
Family( |
69332 | 149 |
plain = "DejaVuSans.ttf", |
150 |
bold = "DejaVuSans-Bold.ttf", |
|
151 |
italic = "DejaVuSans-Oblique.ttf", |
|
152 |
bold_italic = "DejaVuSans-BoldOblique.ttf") |
|
69330 | 153 |
|
69332 | 154 |
def deja_vu_serif: Family = |
69330 | 155 |
Family( |
69332 | 156 |
plain = "DejaVuSerif.ttf", |
157 |
bold = "DejaVuSerif-Bold.ttf", |
|
158 |
italic = "DejaVuSerif-Italic.ttf", |
|
159 |
bold_italic = "DejaVuSerif-BoldItalic.ttf") |
|
69371
3539767d5c61
generate Vacuous font from domain of Isabelle fonts;
wenzelm
parents:
69354
diff
changeset
|
160 |
|
3539767d5c61
generate Vacuous font from domain of Isabelle fonts;
wenzelm
parents:
69354
diff
changeset
|
161 |
def vacuous: Family = Family(plain = "Vacuous.sfd") |
69330 | 162 |
} |
69336 | 163 |
|
164 |
||
165 |
/* build fonts */ |
|
166 |
||
167 |
private def find_file(dirs: List[Path], name: String): Path = |
|
168 |
{ |
|
169 |
val path = Path.explode(name) |
|
170 |
dirs.collectFirst({ case dir if (dir + path).is_file => dir + path }) match { |
|
171 |
case Some(file) => file |
|
172 |
case None => |
|
173 |
error(cat_lines( |
|
174 |
("Failed to find font file " + path + " in directories:") :: |
|
175 |
dirs.map(dir => " " + dir.toString))) |
|
176 |
} |
|
177 |
} |
|
178 |
||
179 |
val default_sources: List[Family] = |
|
180 |
List(Family.deja_vu_sans_mono, Family.deja_vu_sans, Family.deja_vu_serif) |
|
181 |
||
69372 | 182 |
val default_target_dir: Path = Path.explode("isabelle_fonts") |
183 |
||
69336 | 184 |
def build_fonts( |
185 |
sources: List[Family] = default_sources, |
|
186 |
source_dirs: List[Path] = Nil, |
|
187 |
target_prefix: String = "Isabelle", |
|
188 |
target_version: String = "", |
|
69372 | 189 |
target_dir: Path = default_target_dir, |
69336 | 190 |
progress: Progress = No_Progress) |
191 |
{ |
|
69372 | 192 |
progress.echo("Directory " + target_dir) |
69336 | 193 |
Isabelle_System.mkdirs(target_dir) |
194 |
||
69354 | 195 |
val font_dirs = source_dirs ::: List(Path.explode("~~/Admin/isabelle_fonts")) |
196 |
for (dir <- font_dirs if !dir.is_dir) error("Bad source directory: " + dir) |
|
69336 | 197 |
|
69371
3539767d5c61
generate Vacuous font from domain of Isabelle fonts;
wenzelm
parents:
69354
diff
changeset
|
198 |
|
3539767d5c61
generate Vacuous font from domain of Isabelle fonts;
wenzelm
parents:
69354
diff
changeset
|
199 |
// Isabelle fonts |
3539767d5c61
generate Vacuous font from domain of Isabelle fonts;
wenzelm
parents:
69354
diff
changeset
|
200 |
|
3539767d5c61
generate Vacuous font from domain of Isabelle fonts;
wenzelm
parents:
69354
diff
changeset
|
201 |
val targets = |
3539767d5c61
generate Vacuous font from domain of Isabelle fonts;
wenzelm
parents:
69354
diff
changeset
|
202 |
for { source <- sources; (source_font, index) <- source.fonts.zipWithIndex } |
3539767d5c61
generate Vacuous font from domain of Isabelle fonts;
wenzelm
parents:
69354
diff
changeset
|
203 |
yield { |
3539767d5c61
generate Vacuous font from domain of Isabelle fonts;
wenzelm
parents:
69354
diff
changeset
|
204 |
val isabelle_file = find_file(font_dirs, Family.isabelle_text.get(index)) |
3539767d5c61
generate Vacuous font from domain of Isabelle fonts;
wenzelm
parents:
69354
diff
changeset
|
205 |
|
3539767d5c61
generate Vacuous font from domain of Isabelle fonts;
wenzelm
parents:
69354
diff
changeset
|
206 |
val source_file = find_file(font_dirs, source_font) |
3539767d5c61
generate Vacuous font from domain of Isabelle fonts;
wenzelm
parents:
69354
diff
changeset
|
207 |
val source_names = Fontforge.font_names(source_file) |
3539767d5c61
generate Vacuous font from domain of Isabelle fonts;
wenzelm
parents:
69354
diff
changeset
|
208 |
|
3539767d5c61
generate Vacuous font from domain of Isabelle fonts;
wenzelm
parents:
69354
diff
changeset
|
209 |
val target_names = source_names.update(prefix = target_prefix, version = target_version) |
3539767d5c61
generate Vacuous font from domain of Isabelle fonts;
wenzelm
parents:
69354
diff
changeset
|
210 |
val target_file = target_dir + target_names.ttf |
3539767d5c61
generate Vacuous font from domain of Isabelle fonts;
wenzelm
parents:
69354
diff
changeset
|
211 |
|
69372 | 212 |
progress.echo("Font " + target_file.toString + " ...") |
69371
3539767d5c61
generate Vacuous font from domain of Isabelle fonts;
wenzelm
parents:
69354
diff
changeset
|
213 |
Fontforge.execute( |
3539767d5c61
generate Vacuous font from domain of Isabelle fonts;
wenzelm
parents:
69354
diff
changeset
|
214 |
Fontforge.commands( |
3539767d5c61
generate Vacuous font from domain of Isabelle fonts;
wenzelm
parents:
69354
diff
changeset
|
215 |
Fontforge.open(isabelle_file), |
3539767d5c61
generate Vacuous font from domain of Isabelle fonts;
wenzelm
parents:
69354
diff
changeset
|
216 |
Fontforge.select(Range.isabelle_font), |
3539767d5c61
generate Vacuous font from domain of Isabelle fonts;
wenzelm
parents:
69354
diff
changeset
|
217 |
Fontforge.copy, |
3539767d5c61
generate Vacuous font from domain of Isabelle fonts;
wenzelm
parents:
69354
diff
changeset
|
218 |
Fontforge.close, |
69336 | 219 |
|
69371
3539767d5c61
generate Vacuous font from domain of Isabelle fonts;
wenzelm
parents:
69354
diff
changeset
|
220 |
Fontforge.open(source_file), |
3539767d5c61
generate Vacuous font from domain of Isabelle fonts;
wenzelm
parents:
69354
diff
changeset
|
221 |
Fontforge.select(Range.base_font), |
3539767d5c61
generate Vacuous font from domain of Isabelle fonts;
wenzelm
parents:
69354
diff
changeset
|
222 |
Fontforge.select_invert, |
3539767d5c61
generate Vacuous font from domain of Isabelle fonts;
wenzelm
parents:
69354
diff
changeset
|
223 |
Fontforge.clear, |
3539767d5c61
generate Vacuous font from domain of Isabelle fonts;
wenzelm
parents:
69354
diff
changeset
|
224 |
Fontforge.select(Range.isabelle_font), |
3539767d5c61
generate Vacuous font from domain of Isabelle fonts;
wenzelm
parents:
69354
diff
changeset
|
225 |
Fontforge.paste, |
69336 | 226 |
|
69371
3539767d5c61
generate Vacuous font from domain of Isabelle fonts;
wenzelm
parents:
69354
diff
changeset
|
227 |
target_names.set, |
3539767d5c61
generate Vacuous font from domain of Isabelle fonts;
wenzelm
parents:
69354
diff
changeset
|
228 |
Fontforge.generate(target_file), |
3539767d5c61
generate Vacuous font from domain of Isabelle fonts;
wenzelm
parents:
69354
diff
changeset
|
229 |
Fontforge.close) |
3539767d5c61
generate Vacuous font from domain of Isabelle fonts;
wenzelm
parents:
69354
diff
changeset
|
230 |
).check |
3539767d5c61
generate Vacuous font from domain of Isabelle fonts;
wenzelm
parents:
69354
diff
changeset
|
231 |
|
3539767d5c61
generate Vacuous font from domain of Isabelle fonts;
wenzelm
parents:
69354
diff
changeset
|
232 |
(target_file, index) |
3539767d5c61
generate Vacuous font from domain of Isabelle fonts;
wenzelm
parents:
69354
diff
changeset
|
233 |
} |
3539767d5c61
generate Vacuous font from domain of Isabelle fonts;
wenzelm
parents:
69354
diff
changeset
|
234 |
|
3539767d5c61
generate Vacuous font from domain of Isabelle fonts;
wenzelm
parents:
69354
diff
changeset
|
235 |
|
3539767d5c61
generate Vacuous font from domain of Isabelle fonts;
wenzelm
parents:
69354
diff
changeset
|
236 |
// Vacuous font |
3539767d5c61
generate Vacuous font from domain of Isabelle fonts;
wenzelm
parents:
69354
diff
changeset
|
237 |
|
3539767d5c61
generate Vacuous font from domain of Isabelle fonts;
wenzelm
parents:
69354
diff
changeset
|
238 |
{ |
3539767d5c61
generate Vacuous font from domain of Isabelle fonts;
wenzelm
parents:
69354
diff
changeset
|
239 |
val vacuous_file = find_file(font_dirs, Family.vacuous.get(0)) |
3539767d5c61
generate Vacuous font from domain of Isabelle fonts;
wenzelm
parents:
69354
diff
changeset
|
240 |
|
3539767d5c61
generate Vacuous font from domain of Isabelle fonts;
wenzelm
parents:
69354
diff
changeset
|
241 |
val target_names = Fontforge.font_names(vacuous_file) |
69336 | 242 |
val target_file = target_dir + target_names.ttf |
243 |
||
69372 | 244 |
progress.echo("Font " + target_file.toString + " ...") |
69371
3539767d5c61
generate Vacuous font from domain of Isabelle fonts;
wenzelm
parents:
69354
diff
changeset
|
245 |
|
3539767d5c61
generate Vacuous font from domain of Isabelle fonts;
wenzelm
parents:
69354
diff
changeset
|
246 |
val domain = |
3539767d5c61
generate Vacuous font from domain of Isabelle fonts;
wenzelm
parents:
69354
diff
changeset
|
247 |
(for ((target_file, index) <- targets if index == 0) |
3539767d5c61
generate Vacuous font from domain of Isabelle fonts;
wenzelm
parents:
69354
diff
changeset
|
248 |
yield Fontforge.font_domain(target_file)).flatten.toSet.toList.sorted |
3539767d5c61
generate Vacuous font from domain of Isabelle fonts;
wenzelm
parents:
69354
diff
changeset
|
249 |
|
69336 | 250 |
Fontforge.execute( |
251 |
Fontforge.commands( |
|
69371
3539767d5c61
generate Vacuous font from domain of Isabelle fonts;
wenzelm
parents:
69354
diff
changeset
|
252 |
Fontforge.open(vacuous_file), |
3539767d5c61
generate Vacuous font from domain of Isabelle fonts;
wenzelm
parents:
69354
diff
changeset
|
253 |
Fontforge.select(Range.vacuous_font), |
3539767d5c61
generate Vacuous font from domain of Isabelle fonts;
wenzelm
parents:
69354
diff
changeset
|
254 |
Fontforge.copy) + |
69336 | 255 |
|
69371
3539767d5c61
generate Vacuous font from domain of Isabelle fonts;
wenzelm
parents:
69354
diff
changeset
|
256 |
domain.map(code => |
3539767d5c61
generate Vacuous font from domain of Isabelle fonts;
wenzelm
parents:
69354
diff
changeset
|
257 |
Fontforge.commands( |
3539767d5c61
generate Vacuous font from domain of Isabelle fonts;
wenzelm
parents:
69354
diff
changeset
|
258 |
Fontforge.select(Seq(code)), |
3539767d5c61
generate Vacuous font from domain of Isabelle fonts;
wenzelm
parents:
69354
diff
changeset
|
259 |
Fontforge.paste)) |
3539767d5c61
generate Vacuous font from domain of Isabelle fonts;
wenzelm
parents:
69354
diff
changeset
|
260 |
.mkString("\n", "\n", "\n") + |
69336 | 261 |
|
69371
3539767d5c61
generate Vacuous font from domain of Isabelle fonts;
wenzelm
parents:
69354
diff
changeset
|
262 |
Fontforge.commands( |
69336 | 263 |
Fontforge.generate(target_file), |
264 |
Fontforge.close) |
|
265 |
).check |
|
266 |
} |
|
267 |
} |
|
69337 | 268 |
|
269 |
||
270 |
/* Isabelle tool wrapper */ |
|
271 |
||
272 |
val isabelle_tool = |
|
273 |
Isabelle_Tool("build_fonts", "construct Isabelle fonts", args => |
|
274 |
{ |
|
275 |
var source_dirs: List[Path] = Nil |
|
276 |
||
277 |
val getopts = Getopts(""" |
|
278 |
Usage: isabelle build_fonts [OPTIONS] |
|
279 |
||
280 |
Options are: |
|
281 |
-d DIR additional source directory |
|
282 |
||
69343
395c4fb15ea2
use "Isabelle DejaVu" fonts uniformly: Text Area, GUI elements, HTML output etc.;
wenzelm
parents:
69341
diff
changeset
|
283 |
Construct Isabelle fonts from DejaVu font families and Isabelle symbols. |
69337 | 284 |
""", |
285 |
"d:" -> (arg => source_dirs = source_dirs ::: List(Path.explode(arg)))) |
|
286 |
||
287 |
val more_args = getopts(args) |
|
288 |
if (more_args.nonEmpty) getopts.usage() |
|
289 |
||
69372 | 290 |
val target_version = Date.Format("uuuuMMdd")(Date.now()) |
291 |
val target_dir = Path.explode("isabelle_fonts-" + target_version) |
|
292 |
||
69337 | 293 |
val progress = new Console_Progress |
294 |
||
69372 | 295 |
build_fonts(source_dirs = source_dirs, target_dir = target_dir, |
296 |
target_version = target_version, progress = progress) |
|
69337 | 297 |
}) |
69330 | 298 |
} |