beta-0.89.2
[luatex.git] / source / texk / web2c / luatexdir / font / subfont.w
blob0616bdad43ce631a79ffdc0954bb2d05fb6bbb56
1 % subfont.w
3 % Copyright 2005-2006 Han The Thanh <thanh@@pdftex.org>
4 % Copyright 2006-2008 Taco Hoekwater <taco@@luatex.org>
6 % This file is part of LuaTeX.
8 % LuaTeX is free software; you can redistribute it and/or modify it under
9 % the terms of the GNU General Public License as published by the Free
10 % Software Foundation; either version 2 of the License, or (at your
11 % option) any later version.
13 % LuaTeX is distributed in the hope that it will be useful, but WITHOUT
14 % ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
15 % FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
16 % License for more details.
18 % You should have received a copy of the GNU General Public License along
19 % with LuaTeX; if not, see <http://www.gnu.org/licenses/>.
21 @ @c
24 #include "ptexlib.h"
25 #include <string.h>
27 @ @c
28 static struct avl_table *sfd_tree = NULL;
30 static unsigned char *sfd_buffer = NULL;
31 static int sfd_size = 0;
32 static int sfd_curbyte = 0;
34 #define SFD_BUF_SIZE SMALL_BUF_SIZE
36 #define sfd_close() xfclose(sfd_file, cur_file_name)
37 #define sfd_open(a) (sfd_file = fopen((char *)(a), FOPEN_RBIN_MODE))
39 #define sfd_read_file() readbinfile(sfd_file,&sfd_buffer,&sfd_size)
40 #define sfd_getchar() sfd_buffer[sfd_curbyte++]
41 #define sfd_eof() (sfd_curbyte>=sfd_size)
44 static FILE *sfd_file;
45 static char sfd_line[SFD_BUF_SIZE];
47 static subfont_entry *new_subfont_entry(void)
49 int i;
50 subfont_entry *subfont;
51 subfont = xtalloc(1, subfont_entry);
52 subfont->infix = NULL;
53 for (i = 0; i < 256; ++i)
54 subfont->charcodes[i] = -1; /* unassigned */
55 subfont->next = NULL;
56 return subfont;
59 static sfd_entry *new_sfd_entry(void)
61 sfd_entry *sfd;
62 sfd = xtalloc(1, sfd_entry);
63 sfd->name = NULL;
64 sfd->subfont = NULL;
65 return sfd;
68 static void destroy_sfd_entry(void *pa, void *pb)
70 subfont_entry *p, *q;
71 sfd_entry *sfd;
72 sfd = (sfd_entry *) pa;
73 (void) pb;
74 p = sfd->subfont;
75 while (p != NULL) {
76 q = p->next;
77 xfree(p->infix);
78 xfree(p);
79 p = q;
81 xfree(sfd->name);
84 static int comp_sfd_entry(const void *pa, const void *pb, void *p)
86 (void) p;
87 return strcmp(((const sfd_entry *) pa)->name,
88 ((const sfd_entry *) pb)->name);
91 void sfd_free(void)
93 if (sfd_tree != NULL)
94 avl_destroy(sfd_tree, destroy_sfd_entry);
97 static void sfd_getline(boolean expect_eof)
99 char *p;
100 char c;
101 restart:
102 if (sfd_eof()) {
103 if (expect_eof) {
104 if (*sfd_line == '#')
105 *sfd_line = 10;
106 return;
107 } else
108 normal_error("sub font","unexpected end of file");
110 p = sfd_line;
111 do {
112 c = (char) sfd_getchar();
113 append_char_to_buf(c, p, sfd_line, SFD_BUF_SIZE);
114 } while (c != 10 && !sfd_eof());
115 append_eol(p, sfd_line, SFD_BUF_SIZE);
116 if (p - sfd_line < 2 || *sfd_line == '#')
117 goto restart;
120 @ @c
121 static sfd_entry *read_sfd(char *sfd_name)
123 void **aa;
124 sfd_entry *sfd, tmp_sfd;
125 subfont_entry *sf;
127 char buf[SMALL_BUF_SIZE], *p;
128 long int i, j, k;
129 int n;
130 int callback_id = 0;
131 int file_opened = 0;
132 /* check whether this sfd has been read */
133 tmp_sfd.name = sfd_name;
134 if (sfd_tree == NULL) {
135 sfd_tree = avl_create(comp_sfd_entry, NULL, &avl_xallocator);
136 assert(sfd_tree != NULL);
138 sfd = (sfd_entry *) avl_find(sfd_tree, &tmp_sfd);
139 if (sfd != NULL)
140 return sfd;
141 xfree(sfd_buffer);
142 sfd_curbyte = 0;
143 sfd_size = 0;
145 cur_file_name = luatex_find_file(sfd_name, find_sfd_file_callback);
146 if (cur_file_name) {
147 callback_id = callback_defined(read_sfd_file_callback);
148 if (callback_id > 0) {
149 if (!(run_callback(callback_id, "S->bSd", cur_file_name, &file_opened, &sfd_buffer, &sfd_size) &&
150 file_opened && sfd_size > 0)) {
151 formatted_warning("ttf font","cannot open SFD file for reading '%s'", cur_file_name);
152 cur_file_name = NULL;
153 return NULL;
155 } else {
156 if (!sfd_open(cur_file_name)) {
157 formatted_warning("ttf font", "cannot open SFD file for reading '%s'", cur_file_name);
158 cur_file_name = NULL;
159 return NULL;
161 sfd_read_file();
162 sfd_close();
165 tex_printf("{");
166 tex_printf("%s", cur_file_name);
167 sfd = new_sfd_entry();
168 sfd->name = xstrdup(sfd_name);
169 while (!sfd_eof()) {
170 sfd_getline(true);
171 if (*sfd_line == 10) /* empty line indicating eof */
172 break;
173 sf = new_subfont_entry();
174 sf->next = sfd->subfont;
175 sfd->subfont = sf;
176 sscanf(sfd_line, "%s %n", buf, &n);
177 sf->infix = xstrdup(buf);
178 p = sfd_line + n; /* skip to the next word */
179 k = 0;
180 read_ranges:
181 for (;;) {
182 if (*p == '\\') { /* continue on next line */
183 sfd_getline(false);
184 p = sfd_line;
185 goto read_ranges;
186 } else if (*p == 0) /* end of subfont */
187 break;
188 if (sscanf(p, " %li %n", &i, &n) == 0)
189 formatted_error("sub font","invalid token: %s", p);
190 p += n;
191 if (*p == ':') { /* offset */
192 k = i;
193 p++;
194 } else if (*p == '_') { /* range */
195 if (sscanf(p + 1, " %li %n", &j, &n) == 0)
196 formatted_error("sub font","invalid token: %s", p);
197 if (i > j || k + (j - i) > 255)
198 formatted_error("sub font","invalid range: %s", p);
199 while (i <= j)
200 sf->charcodes[k++] = i++;
201 p += n + 1;
202 } else /* codepoint */
203 sf->charcodes[k++] = i;
206 tex_printf("}");
207 aa = avl_probe(sfd_tree, sfd);
208 assert(aa != NULL);
209 return sfd;
212 @ @c
213 boolean handle_subfont_fm(fm_entry * fm, int mode)
215 size_t l;
216 char *p, *q, *r;
217 sfd_entry *sfd;
218 subfont_entry *sf;
219 fm_entry *fm2;
220 char buf[SMALL_BUF_SIZE];
221 assert(fm->tfm_name != NULL);
222 p = fm->tfm_name;
223 q = strchr(p, '@@'); /* search for the first '@@' */
224 if (q == NULL)
225 return false;
226 r = strchr(q + 1, '@@'); /* search for the second '@@' */
227 if (r == NULL)
228 return false;
229 if (q <= p || r <= q + 1 /* prefix or sfd name is empty */
230 || r - p != (int) strlen(p) - 1) /* or the second '@@' is not the last char yet */
231 return false;
232 l = (size_t) (r - (q + 1)); /* length of sfd name */
233 strncpy(buf, q + 1, l);
234 buf[l] = 0;
235 check_buf(strlen(buf) + 4, SMALL_BUF_SIZE);
236 strcat(buf, ".sfd");
237 sfd = read_sfd(buf);
238 if (sfd == NULL)
239 return false;
240 /* at this point we know fm is a subfont */
241 set_subfont(fm);
242 xfree(fm->ps_name);
243 /* set default values for PidEid */
244 if (fm->pid == -1) {
245 fm->pid = 3;
246 fm->eid = 1;
248 l = (size_t) (q - p); /* length of base tfm name (prefix) */
249 for (sf = sfd->subfont; sf != NULL; sf = sf->next) {
250 strncpy(buf, p, l);
251 buf[l] = 0;
252 strcat(buf, sf->infix);
253 fm2 = new_fm_entry();
254 fm2->tfm_name = xstrdup(buf);
255 fm2->ff_name = xstrdup(fm->ff_name);
256 fm2->type = fm->type;
257 fm2->pid = fm->pid;
258 fm2->eid = fm->eid;
259 fm2->subfont = sf;
260 if (avl_do_entry(fm2, mode) != 0) /* try to insert the entry */
261 delete_fm_entry(fm2); /* delete it if failed */
263 delete_fm_entry(fm);
264 return true;