10 |
10 |
11 import java.io.{File => JFile} |
11 import java.io.{File => JFile} |
12 import java.util.Locale |
12 import java.util.Locale |
13 |
13 |
14 |
14 |
15 object Fontforge |
15 object Fontforge { |
16 { |
|
17 /** scripting language **/ |
16 /** scripting language **/ |
18 |
17 |
19 type Script = String |
18 type Script = String |
20 |
19 |
21 |
20 |
22 /* concrete syntax */ |
21 /* concrete syntax */ |
23 |
22 |
24 def string(s: String): Script = |
23 def string(s: String): Script = { |
25 { |
|
26 def err(c: Char): Nothing = |
24 def err(c: Char): Nothing = |
27 error("Bad character \\u" + String.format(Locale.ROOT, "%04x", Integer.valueOf(c)) + |
25 error("Bad character \\u" + String.format(Locale.ROOT, "%04x", Integer.valueOf(c)) + |
28 " in fontforge string " + quote(s)) |
26 " in fontforge string " + quote(s)) |
29 |
27 |
30 val q = if (s.contains('"')) '\'' else '"' |
28 val q = if (s.contains('"')) '\'' else '"' |
31 |
29 |
32 def escape(c: Char): String = |
30 def escape(c: Char): String = { |
33 { |
|
34 if (c == '\u0000' || c == '\r' || c == q) err(c) |
31 if (c == '\u0000' || c == '\r' || c == q) err(c) |
35 else if (c == '\n') "\\n" |
32 else if (c == '\n') "\\n" |
36 else if (c == '\\') "\\\\" |
33 else if (c == '\\') "\\\\" |
37 else c.toString |
34 else c.toString |
38 } |
35 } |
68 |
65 |
69 |
66 |
70 /** execute fontforge program **/ |
67 /** execute fontforge program **/ |
71 |
68 |
72 def execute(script: Script, args: String = "", cwd: JFile = null): Process_Result = |
69 def execute(script: Script, args: String = "", cwd: JFile = null): Process_Result = |
73 Isabelle_System.with_tmp_file("fontforge")(script_file => |
70 Isabelle_System.with_tmp_file("fontforge")(script_file => { |
74 { |
|
75 File.write(script_file, script) |
71 File.write(script_file, script) |
76 Isabelle_System.bash(File.bash_path(Path.explode("$ISABELLE_FONTFORGE")) + |
72 Isabelle_System.bash(File.bash_path(Path.explode("$ISABELLE_FONTFORGE")) + |
77 " -lang=ff -script " + File.bash_path(script_file) + " " + args) |
73 " -lang=ff -script " + File.bash_path(script_file) + " " + args) |
78 }) |
74 }) |
79 |
75 |
80 def font_domain(path: Path, strict: Boolean = false): List[Int] = |
76 def font_domain(path: Path, strict: Boolean = false): List[Int] = { |
81 { |
|
82 val script = |
77 val script = |
83 commands( |
78 commands( |
84 open(path), |
79 open(path), |
85 "i = 0", |
80 "i = 0", |
86 "while (i < CharCnt() && i < 0x110000)", |
81 "while (i < CharCnt() && i < 0x110000)", |
98 fontname: String = "", |
93 fontname: String = "", |
99 familyname: String = "", |
94 familyname: String = "", |
100 fullname: String = "", |
95 fullname: String = "", |
101 weight: String = "", |
96 weight: String = "", |
102 copyright: String = "", |
97 copyright: String = "", |
103 fontversion: String = "") |
98 fontversion: String = "" |
104 { |
99 ) { |
105 override def toString: String = fontname |
100 override def toString: String = fontname |
106 |
101 |
107 def ttf: Path = Path.explode(fontname).ext("ttf") |
102 def ttf: Path = Path.explode(fontname).ext("ttf") |
108 |
103 |
109 def update(prefix: String = "", version: String = ""): Font_Names = |
104 def update(prefix: String = "", version: String = ""): Font_Names = { |
110 { |
|
111 val fontversion1 = proper_string(version) getOrElse fontversion |
105 val fontversion1 = proper_string(version) getOrElse fontversion |
112 if (prefix == "") copy(fontversion = fontversion1) |
106 if (prefix == "") copy(fontversion = fontversion1) |
113 else { |
107 else { |
114 copy(fontname = prefix + fontname, |
108 copy(fontname = prefix + fontname, |
115 familyname = prefix + " " + familyname, |
109 familyname = prefix + " " + familyname, |
123 def set: Script = |
117 def set: Script = |
124 List(fontname, familyname, fullname, weight, copyright, fontversion).map(string). |
118 List(fontname, familyname, fullname, weight, copyright, fontversion).map(string). |
125 mkString("SetFontNames(", ",", ")") |
119 mkString("SetFontNames(", ",", ")") |
126 } |
120 } |
127 |
121 |
128 def font_names(path: Path): Font_Names = |
122 def font_names(path: Path): Font_Names = { |
129 { |
|
130 val script = |
123 val script = |
131 commands( |
124 commands( |
132 open(path), |
125 open(path), |
133 "Print($fontname)", |
126 "Print($fontname)", |
134 "Print($familyname)", |
127 "Print($familyname)", |