3 This is dvipdfmx, an eXtended version of dvipdfm by Mark A. Wicks.
5 Copyright (C) 2002-2012 by Jin-Hwan Cho and Shunsaku Hirata,
6 the dvipdfmx project team.
8 This program is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 2 of the License, or
11 (at your option) any later version.
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with this program; if not, write to the Free Software
20 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
25 #endif /* _HAVE_CONFIG_H */
40 #define VERBOSE_LEVEL_MIN 0
41 static int verbose = 0;
43 otl_conf_set_verbose (void)
49 parse_uc_coverage (pdf_obj *gclass, const char **pp, const char *endptr)
54 char *glyphname, *glyphclass;
56 if (*pp + 1 >= endptr)
62 coverage = pdf_new_array();
64 while (*pp < endptr) {
65 skip_white(pp, endptr);
80 glyphclass = parse_c_ident(pp, endptr);
81 cvalues = pdf_lookup_dict(gclass, glyphclass);
83 ERROR("%s not defined...", glyphclass);
84 size = pdf_array_length(cvalues);
85 for (i = 0; i < size; i++) {
86 pdf_add_array(coverage,
87 pdf_link_obj(pdf_get_array(cvalues, i)));
92 glyphname = parse_c_ident(pp, endptr);
94 ERROR("Invalid Unicode character specified.");
96 skip_white(pp, endptr);
97 if (*pp + 1 < endptr && **pp == '-') {
98 value = pdf_new_array();
100 if (agl_get_unicodes(glyphname, &ucv, 1) != 1)
101 ERROR("Invalid Unicode char: %s", glyphname);
102 pdf_add_array(value, pdf_new_number(ucv));
105 (*pp)++; skip_white(pp, endptr);
106 glyphname = parse_c_ident(pp, endptr);
108 ERROR("Invalid Unicode char: %s", glyphname);
109 if (agl_get_unicodes(glyphname, &ucv, 1) != 1)
110 ERROR("Invalid Unicode char: %s", glyphname);
111 pdf_add_array(value, pdf_new_number(ucv));
115 if (agl_get_unicodes(glyphname, &ucv, 1) != 1)
116 ERROR("Invalid Unicode char: %s", glyphname);
117 value = pdf_new_number(ucv);
120 pdf_add_array(coverage, value);
123 skip_white(pp, endptr);
129 static pdf_obj *parse_block (pdf_obj *gclass, const char **pp, const char *endptr);
132 add_rule (pdf_obj *rule, pdf_obj *gclass,
133 char *first, char *second, char *suffix)
135 pdf_obj *glyph1, *glyph2;
136 #define MAX_UNICODES 16
137 long unicodes[MAX_UNICODES];
140 if (first[0] == '@') {
141 glyph1 = pdf_lookup_dict(gclass, &first[1]);
143 WARN("No glyph class \"%s\" found.", &first[1]);
146 pdf_link_obj(glyph1);
148 if (verbose > VERBOSE_LEVEL_MIN) {
149 MESG("otl_conf>> Output glyph sequence: %s\n", first);
153 n_unicodes = agl_get_unicodes(first, unicodes, MAX_UNICODES);
154 if (n_unicodes < 1) {
155 WARN("Failed to convert glyph \"%s\" to Unicode sequence.",
159 glyph1 = pdf_new_array();
161 if (verbose > VERBOSE_LEVEL_MIN) {
162 MESG("otl_conf>> Output glyph sequence: %s ->", first);
165 for (i = 0; i < n_unicodes; i++) {
166 pdf_add_array(glyph1, pdf_new_number(unicodes[i]));
168 if (verbose > VERBOSE_LEVEL_MIN) {
169 if (unicodes[i] < 0x10000) {
170 MESG(" U+%04X", unicodes[i]);
172 MESG(" U+%06X", unicodes[i]);
177 if (verbose > VERBOSE_LEVEL_MIN) {
182 if (second[0] == '@') {
183 glyph2 = pdf_lookup_dict(gclass, &second[1]);
185 WARN("No glyph class \"%s\" found.", &second[1]);
188 pdf_link_obj(glyph2);
190 if (verbose > VERBOSE_LEVEL_MIN) {
191 MESG("otl_conf>> Input glyph sequence: %s (%s)\n", second, suffix);
195 n_unicodes = agl_get_unicodes(second, unicodes, 16);
196 if (n_unicodes < 1) {
197 WARN("Failed to convert glyph \"%s\" to Unicode sequence.",
202 if (verbose > VERBOSE_LEVEL_MIN) {
204 MESG("otl_conf>> Input glyph sequence: %s.%s ->", second, suffix);
206 MESG("otl_conf>> Input glyph sequence: %s ->", second);
209 glyph2 = pdf_new_array();
210 for (i = 0; i < n_unicodes; i++) {
211 pdf_add_array(glyph2, pdf_new_number(unicodes[i]));
213 if (verbose > VERBOSE_LEVEL_MIN) {
214 if (unicodes[i] < 0x10000) {
215 MESG(" U+%04X", unicodes[i]);
217 MESG(" U+%06X", unicodes[i]);
221 if (verbose > VERBOSE_LEVEL_MIN) {
222 MESG(" (%s)\n", suffix);
228 pdf_add_array(rule, pdf_new_string(suffix, strlen(suffix)));
230 pdf_add_array(rule, pdf_new_null());
232 pdf_add_array(rule, glyph1);
233 pdf_add_array(rule, glyph2);
237 parse_substrule (pdf_obj *gclass, const char **pp, const char *endptr)
242 skip_white(pp, endptr);
243 if (*pp < endptr && **pp == '{')
246 skip_white(pp, endptr);
250 substrule = pdf_new_array();
251 while (*pp < endptr && **pp != '}') {
252 skip_white(pp, endptr);
257 while (*pp < endptr) {
258 if (**pp == '\r' || **pp == '\n') {
265 } else if (**pp == ';') {
270 skip_white(pp, endptr);
271 token = parse_c_ident(pp, endptr);
275 if (!strcmp(token, "assign") || !strcmp(token, "substitute")) {
276 char *tmp, *first, *second, *suffix;
278 skip_white(pp, endptr);
280 first = parse_c_ident(pp, endptr);
282 ERROR("Syntax error (1)");
284 skip_white(pp, endptr);
285 tmp = parse_c_ident(pp, endptr);
286 if (strcmp(tmp, "by") && strcmp(tmp, "to"))
287 ERROR("Syntax error (2): %s", *pp);
289 skip_white(pp, endptr);
290 second = parse_c_ident(pp, endptr); /* allows @ */
292 ERROR("Syntax error (3)");
294 /* (assign|substitute) tag dst src */
295 pdf_add_array(substrule, pdf_new_name(token));
296 if (*pp + 1 < endptr && **pp == '.') {
298 suffix = parse_c_ident(pp, endptr);
302 add_rule(substrule, gclass, first, second, suffix);
310 ERROR("Unkown command %s.", token);
313 skip_white(pp, endptr);
316 if (*pp < endptr && **pp == '}')
322 parse_block (pdf_obj *gclass, const char **pp, const char *endptr)
327 skip_white(pp, endptr);
328 if (*pp < endptr && **pp == '{')
331 skip_white(pp, endptr);
335 rule = pdf_new_dict();
336 while (*pp < endptr && **pp != '}') {
337 skip_white(pp, endptr);
341 while (*pp < endptr) {
342 if (**pp == '\r' || **pp == '\n') {
349 } else if (**pp == ';') {
354 skip_white(pp, endptr);
355 token = parse_c_ident(pp, endptr);
359 if (!strcmp(token, "script") ||
360 !strcmp(token, "language")) {
363 skip_white(pp, endptr);
365 while (*pp + len < endptr && *(*pp + len) != ';') {
369 tmp = NEW(len+1, char);
370 memset(tmp, 0, len+1);
371 for (i = 0; i < len; i++) {
378 pdf_new_string(tmp, strlen(tmp)));
380 if (verbose > VERBOSE_LEVEL_MIN) {
381 MESG("otl_conf>> Current %s set to \"%s\"\n", token, tmp);
386 } else if (!strcmp(token, "option")) {
387 pdf_obj *opt_dict, *opt_rule;
389 opt_dict = pdf_lookup_dict(rule, "option");
391 opt_dict = pdf_new_dict();
393 pdf_new_name("option"), opt_dict);
396 skip_white(pp, endptr);
397 tmp = parse_c_ident(pp, endptr);
399 if (verbose > VERBOSE_LEVEL_MIN) {
400 MESG("otl_conf>> Reading option \"%s\"\n", tmp);
403 skip_white(pp, endptr);
404 opt_rule = parse_block(gclass, pp, endptr);
405 pdf_add_dict(opt_dict, pdf_new_name(tmp), opt_rule);
408 } else if (!strcmp(token, "prefered") ||
409 !strcmp(token, "required") ||
410 !strcmp(token, "optional")) {
411 pdf_obj *subst, *rule_block;
413 if (verbose > VERBOSE_LEVEL_MIN) {
414 MESG("otl_conf>> Reading block (%s)\n", token);
417 skip_white(pp, endptr);
418 if (*pp >= endptr || **pp != '{')
419 ERROR("Syntax error (1)");
421 rule_block = parse_substrule(gclass, pp, endptr);
422 subst = pdf_lookup_dict(rule, "rule");
424 subst = pdf_new_array();
425 pdf_add_dict(rule, pdf_new_name("rule"), subst);
427 pdf_add_array(subst, pdf_new_number(token[0]));
428 pdf_add_array(subst, rule_block);
429 } else if (token[0] == '@') {
432 skip_white(pp, endptr);
434 skip_white(pp, endptr);
436 if (verbose > VERBOSE_LEVEL_MIN) {
437 MESG("otl_conf>> Glyph class \"%s\"\n", token);
440 coverage = parse_uc_coverage(gclass, pp, endptr);
442 ERROR("No valid Unicode characters...");
445 pdf_new_name(&token[1]), coverage);
448 skip_white(pp, endptr);
451 if (*pp < endptr && **pp == '}')
458 otl_read_conf (const char *conf_name)
463 char *filename, *wbuf, *p, *endptr;
467 filename = NEW(strlen(conf_name)+strlen(".otl")+1, char);
468 strcpy(filename, conf_name);
469 strcat(filename, ".otl");
471 fp = DPXFOPEN(filename, DPX_RES_TYPE_TEXT);
477 size = file_size(fp);
480 if (verbose > VERBOSE_LEVEL_MIN) {
482 MESG("otl_conf>> Layout config. \"%s\" found: file=\"%s\" (%ld bytes)\n",
483 conf_name, filename, size);
489 wbuf = NEW(size, char);
490 p = wbuf; endptr = p + size;
491 while (size > 0 && p < endptr) {
492 len = fread(p, sizeof(char), size, fp);
498 gclass = pdf_new_dict();
499 rule = parse_block(gclass, &pp, endptr);
500 pdf_release_obj(gclass);
507 static pdf_obj *otl_confs = NULL;
510 otl_find_conf (const char *conf_name)
513 pdf_obj *script, *language;
519 rule = pdf_lookup_dict(otl_confs, conf_name);
521 otl_confs = pdf_new_dict();
526 rule = otl_read_conf(conf_name);
528 pdf_add_dict(otl_confs,
529 pdf_new_name(conf_name), rule);
530 script = pdf_lookup_dict(rule, "script");
531 language = pdf_lookup_dict(rule, "language");
532 options = pdf_lookup_dict(rule, "option");
534 script = pdf_new_string("*", 1);
536 pdf_new_name("script"),
538 WARN("Script unspecified in \"%s\"...", conf_name);
541 language = pdf_new_string("dflt", 4);
543 pdf_new_name("language"),
545 WARN("Language unspecified in \"%s\"...", conf_name);
549 pdf_obj *optkeys, *opt, *key;
552 optkeys = pdf_dict_keys(options);
553 num_opts = pdf_array_length(optkeys);
554 for (i = 0; i < num_opts; i++) {
555 key = pdf_get_array(optkeys, i);
556 opt = pdf_lookup_dict(options, pdf_name_value(key));
557 if (!pdf_lookup_dict(opt, "script"))
559 pdf_new_name("script"),
560 pdf_link_obj(script));
561 if (!pdf_lookup_dict(opt, "language"))
563 pdf_new_name("language"),
564 pdf_link_obj(language));
566 pdf_release_obj(optkeys);
577 otl_conf_get_script (pdf_obj *conf)
583 script = pdf_lookup_dict(conf, "script");
585 return pdf_string_value(script);
589 otl_conf_get_language (pdf_obj *conf)
595 language = pdf_lookup_dict(conf, "language");
597 return pdf_string_value(language);
601 otl_conf_get_rule (pdf_obj *conf)
604 return pdf_lookup_dict(conf, "rule");
608 otl_conf_find_opt (pdf_obj *conf, const char *opt_tag)
610 pdf_obj *opt_conf = NULL;
615 options = pdf_lookup_dict(conf, "option");
616 if (options && opt_tag)
617 opt_conf = pdf_lookup_dict(options, opt_tag);
628 pdf_release_obj(otl_confs);
629 otl_confs = pdf_new_dict();
631 if (verbose > VERBOSE_LEVEL_MIN + 10) {
632 pdf_release_obj(pdf_ref_obj(otl_confs));
637 otl_close_conf (void)
639 pdf_release_obj(otl_confs);