summaryrefslogtreecommitdiff
path: root/Build/source/texk/dvipdfm-x/vf.c
diff options
context:
space:
mode:
Diffstat (limited to 'Build/source/texk/dvipdfm-x/vf.c')
-rw-r--r--Build/source/texk/dvipdfm-x/vf.c572
1 files changed, 572 insertions, 0 deletions
diff --git a/Build/source/texk/dvipdfm-x/vf.c b/Build/source/texk/dvipdfm-x/vf.c
new file mode 100644
index 00000000000..835e85de701
--- /dev/null
+++ b/Build/source/texk/dvipdfm-x/vf.c
@@ -0,0 +1,572 @@
+/* This is dvipdfmx, an eXtended version of dvipdfm by Mark A. Wicks.
+
+ Copyright (C) 2002-2020 by Jin-Hwan Cho and Shunsaku Hirata,
+ the dvipdfmx project team.
+
+ Copyright (C) 1998, 1999 by Mark A. Wicks <mwicks@kettering.edu>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+*/
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "system.h"
+#include "numbers.h"
+#include "error.h"
+#include "mem.h"
+#include "dpxconf.h"
+#include "dpxfile.h"
+/* pdfdev... */
+#include "pdfdev.h"
+
+#include "tfm.h"
+#include "dvi.h"
+#include "vf.h"
+#include "dvipdfmx.h"
+
+#include "dvicodes.h"
+
+#define VF_ALLOC_SIZE 16u
+
+#define VF_ID 202
+#define FIX_WORD_BASE 1048576.0
+#define TEXPT2PT (72.0/72.27)
+#define FW2PT (TEXPT2PT/((double)(FIX_WORD_BASE)))
+
+struct font_def {
+ int32_t font_id /* id used internally in vf file */;
+ uint32_t checksum, size, design_size;
+ char *directory, *name;
+ int tfm_id; /* id returned by TFM module */
+ int dev_id; /* id returned by DEV module */
+};
+
+struct vf
+{
+ char *tex_name;
+ spt_t ptsize;
+ uint32_t design_size; /* A fixword-pts quantity */
+ int num_dev_fonts, max_dev_fonts;
+ struct font_def *dev_fonts;
+ unsigned char **ch_pkt, message_flag;
+ uint32_t *pkt_len;
+ unsigned num_chars;
+};
+
+struct vf *vf_fonts = NULL;
+int num_vf_fonts = 0, max_vf_fonts = 0;
+
+static void read_header(FILE *vf_file, int thisfont)
+{
+ /* Check for usual signature */
+ if (get_unsigned_byte (vf_file) == PRE &&
+ get_unsigned_byte (vf_file) == VF_ID) {
+
+ /* If here, assume it's a legitimate vf file */
+
+ /* skip comment */
+ skip_bytes (get_unsigned_byte (vf_file), vf_file);
+
+ /* Skip checksum */
+ skip_bytes (4, vf_file);
+
+ vf_fonts[thisfont].design_size = get_positive_quad(vf_file, "VF", "design_size");
+ } else { /* Try to fail gracefully and return an error to caller */
+ fprintf (stderr, "VF file may be corrupt\n");
+ }
+}
+
+
+static void resize_vf_fonts(int size)
+{
+ int i;
+ if (size > max_vf_fonts) {
+ vf_fonts = RENEW (vf_fonts, size, struct vf);
+ for (i=max_vf_fonts; i<size; i++) {
+ vf_fonts[i].num_dev_fonts = 0;
+ vf_fonts[i].max_dev_fonts = 0;
+ vf_fonts[i].dev_fonts = NULL;
+ vf_fonts[i].message_flag = 0;
+ }
+ max_vf_fonts = size;
+ }
+ return;
+}
+
+static void resize_one_vf_font (struct vf *a_vf, unsigned size)
+{
+ unsigned i;
+ if (size > (a_vf->num_chars)) {
+ size = MAX (size, a_vf->num_chars+256);
+ a_vf->ch_pkt = RENEW (a_vf->ch_pkt, size, unsigned char *);
+ a_vf->pkt_len = RENEW (a_vf->pkt_len, size, uint32_t);
+ for (i=a_vf->num_chars; i<size; i++) {
+ (a_vf->ch_pkt)[i] = NULL;
+ (a_vf->pkt_len)[i] = 0;
+ }
+ a_vf->num_chars = size;
+ }
+}
+
+static void read_a_char_def(FILE *vf_file, int thisfont, uint32_t pkt_len,
+ uint32_t ch)
+{
+ unsigned char *pkt;
+#ifdef DEBUG
+ fprintf (stderr, "read_a_char_def: len=%u, ch=%u\n", pkt_len, ch);
+#endif
+ /* Resize and initialize character arrays if necessary */
+ if (ch >= vf_fonts[thisfont].num_chars) {
+ resize_one_vf_font (vf_fonts+thisfont, ch+1);
+ }
+ if (pkt_len > 0) {
+ pkt = NEW (pkt_len, unsigned char);
+ if (fread (pkt, 1, pkt_len, vf_file) != pkt_len)
+ ERROR ("VF file ended prematurely.");
+ (vf_fonts[thisfont].ch_pkt)[ch] = pkt;
+ }
+ (vf_fonts[thisfont].pkt_len)[ch] = pkt_len;
+ return;
+}
+
+static void read_a_font_def(FILE *vf_file, int32_t font_id, int thisfont)
+{
+ struct font_def *dev_font;
+ int dir_length, name_length;
+#ifdef DEBUG
+ fprintf (stderr, "read_a_font_def: font_id = %d\n", font_id);
+#endif
+ if (vf_fonts[thisfont].num_dev_fonts >=
+ vf_fonts[thisfont].max_dev_fonts) {
+ vf_fonts[thisfont].max_dev_fonts += VF_ALLOC_SIZE;
+ vf_fonts[thisfont].dev_fonts = RENEW
+ (vf_fonts[thisfont].dev_fonts,
+ vf_fonts[thisfont].max_dev_fonts,
+ struct font_def);
+ }
+ dev_font = vf_fonts[thisfont].dev_fonts+
+ vf_fonts[thisfont].num_dev_fonts;
+ dev_font -> font_id = font_id;
+ dev_font -> checksum = get_unsigned_quad (vf_file);
+ dev_font -> size = get_positive_quad (vf_file, "VF", "font_size");
+ dev_font -> design_size = get_positive_quad (vf_file, "VF", "font_design_size");
+ dir_length = get_unsigned_byte (vf_file);
+ name_length = get_unsigned_byte (vf_file);
+ dev_font -> directory = NEW (dir_length+1, char);
+ dev_font -> name = NEW (name_length+1, char);
+ fread (dev_font -> directory, 1, dir_length, vf_file);
+ fread (dev_font -> name, 1, name_length, vf_file);
+ (dev_font -> directory)[dir_length] = 0;
+ (dev_font -> name)[name_length] = 0;
+ vf_fonts[thisfont].num_dev_fonts += 1;
+ dev_font->tfm_id = tfm_open (dev_font -> name, 1); /* must exist */
+ dev_font->dev_id =
+ dvi_locate_font (dev_font->name,
+ sqxfw (vf_fonts[thisfont].ptsize,
+ dev_font->size));
+#ifdef DEBUG
+ fprintf (stderr, "[%s/%s]\n", dev_font -> directory, dev_font -> name);
+#endif
+ return;
+}
+
+static void process_vf_file (FILE *vf_file, int thisfont)
+{
+ int eof = 0, code;
+ int32_t font_id;
+ while (!eof) {
+ code = get_unsigned_byte (vf_file);
+ switch (code) {
+ case FNT_DEF1: case FNT_DEF2: case FNT_DEF3: case FNT_DEF4:
+ font_id = get_unsigned_num (vf_file, code-FNT_DEF1);
+ read_a_font_def (vf_file, font_id, thisfont);
+ break;
+ default:
+ if (code < 242) {
+ /* For a short packet, code is the pkt_len */
+ uint32_t ch = get_unsigned_byte (vf_file);
+ /* Skip over TFM width since we already know it */
+ skip_bytes (3, vf_file);
+ read_a_char_def (vf_file, thisfont, code, ch);
+ break;
+ }
+ if (code == 242) {
+ uint32_t pkt_len = get_positive_quad (vf_file, "VF", "pkt_len");
+ uint32_t ch = get_unsigned_quad (vf_file);
+ /* Skip over TFM width since we already know it */
+ skip_bytes (4, vf_file);
+ if (ch < 0x1000000U)
+ read_a_char_def (vf_file, thisfont, pkt_len, ch);
+ else {
+ fprintf (stderr, "char=%u\n", ch);
+ ERROR ("Long character (>24 bits) in VF file.\nI can't handle long characters!\n");
+ }
+ break;
+ }
+ if (code == POST) {
+ eof = 1;
+ break;
+ }
+ fprintf (stderr, "Quitting on code=%d\n", code);
+ eof = 1;
+ break;
+ }
+ }
+ return;
+}
+
+/* Unfortunately, the following code isn't smart enough
+ to load the vf only once for multiple point sizes.
+ You will get a separate copy of each VF in memory (and a separate
+ opening and reading of the file) for
+ each point size. Since VFs are pretty small, I guess
+ this is tolerable for now. In any case,
+ the PDF file will never repeat a physical font name */
+/* Note: This code needs to be able to recurse */
+/* Global variables such as num_vf_fonts require careful attention */
+int vf_locate_font (const char *tex_name, spt_t ptsize)
+{
+ int thisfont = -1, i;
+ char *full_vf_file_name;
+ FILE *vf_file;
+ /* Has this name and ptsize already been loaded as a VF? */
+ for (i=0; i<num_vf_fonts; i++) {
+ if (!strcmp (vf_fonts[i].tex_name, tex_name) &&
+ vf_fonts[i].ptsize == ptsize)
+ break;
+ }
+ if (i != num_vf_fonts) {
+ thisfont = i;
+ } else {
+ /* It's hasn't already been loaded as a VF, so try to load it */
+ full_vf_file_name = kpse_find_file (tex_name,
+ kpse_vf_format,
+ 1);
+ if (!full_vf_file_name) {
+ full_vf_file_name = kpse_find_file (tex_name,
+ kpse_ovf_format,
+ 1);
+ }
+ if (full_vf_file_name &&
+ (vf_file = MFOPEN (full_vf_file_name, FOPEN_RBIN_MODE)) != NULL) {
+ if (dpx_conf.verbose_level == 1)
+ fprintf (stderr, "(VF:%s", tex_name);
+ if (dpx_conf.verbose_level > 1)
+ fprintf (stderr, "(VF:%s", full_vf_file_name);
+ if (num_vf_fonts >= max_vf_fonts) {
+ resize_vf_fonts (max_vf_fonts + VF_ALLOC_SIZE);
+ }
+ thisfont = num_vf_fonts++;
+ { /* Initialize some pointers and such */
+ vf_fonts[thisfont].tex_name = NEW (strlen(tex_name)+1, char);
+ strcpy (vf_fonts[thisfont].tex_name, tex_name);
+ vf_fonts[thisfont].ptsize = ptsize;
+ vf_fonts[thisfont].num_chars = 0;
+ vf_fonts[thisfont].ch_pkt = NULL;
+ vf_fonts[thisfont].pkt_len = NULL;
+ }
+ read_header(vf_file, thisfont);
+ process_vf_file (vf_file, thisfont);
+ if (dpx_conf.verbose_level > 0)
+ fprintf (stderr, ")");
+ MFCLOSE (vf_file);
+ }
+ if (full_vf_file_name)
+ RELEASE(full_vf_file_name);
+ }
+ return thisfont;
+}
+
+#define next_byte() (*((*start)++))
+static int unsigned_byte (unsigned char **start, unsigned char *end)
+{
+ int byte = 0;
+ if (*start < end)
+ byte = next_byte();
+ else
+ ERROR ("Premature end of DVI byte stream in VF font\n");
+ return byte;
+}
+
+static int32_t get_pkt_signed_num (unsigned char **start, unsigned char *end,
+ unsigned char num)
+{
+ int32_t val = 0;
+ if (end-*start > num) {
+ val = next_byte();
+ if (val > 0x7f)
+ val -= 0x100;
+ switch (num) {
+ case 3: val = (val << 8) | next_byte();
+ case 2: val = (val << 8) | next_byte();
+ case 1: val = (val << 8) | next_byte();
+ default: break;
+ }
+ } else
+ ERROR ("Premature end of DVI byte stream in VF font\n");
+ return val;
+}
+
+static int32_t get_pkt_unsigned_num (unsigned char **start, unsigned char *end,
+ unsigned char num)
+{
+ int32_t val = 0;
+ if (end-*start > num) {
+ val = next_byte();
+ switch (num) {
+ case 3: if (val > 0x7f)
+ val -= 0x100;
+ val = (val << 8) | next_byte();
+ case 2: val = (val << 8) | next_byte();
+ case 1: val = (val << 8) | next_byte();
+ default: break;
+ }
+ } else
+ ERROR ("Premature end of DVI byte stream in VF font\n");
+ return val;
+}
+
+static void vf_putrule (unsigned char **start, unsigned char *end, spt_t ptsize)
+{
+ int32_t height = get_pkt_signed_num (start, end, 3);
+ int32_t width = get_pkt_signed_num (start, end, 3);
+ dvi_rule (sqxfw (ptsize, width), sqxfw (ptsize, height));
+}
+
+static void vf_setrule (unsigned char **start, unsigned char *end, spt_t ptsize)
+{
+ int32_t height = get_pkt_signed_num (start, end, 3);
+ int32_t s_width = sqxfw (ptsize, get_pkt_signed_num (start, end, 3));
+ dvi_rule (s_width, sqxfw (ptsize, height));
+ dvi_right (s_width);
+}
+
+static void vf_fnt (int32_t font_id, int vf_font)
+{
+ int i;
+ for (i=0; i<vf_fonts[vf_font].num_dev_fonts; i++) {
+ if (font_id == ((vf_fonts[vf_font].dev_fonts)[i]).font_id) {
+ break;
+ }
+ }
+ if (i < vf_fonts[vf_font].num_dev_fonts) { /* Font was found */
+ dvi_set_font ((vf_fonts[vf_font].dev_fonts[i]).dev_id);
+ } else {
+ fprintf (stderr, "Font_id: %d not found in VF\n", font_id);
+ }
+}
+
+/* identical to do_xxx in dvi.c */
+static void vf_xxx (int32_t len, unsigned char **start, unsigned char *end)
+{
+ if (*start <= end - len) {
+ unsigned char *buffer = NEW(len+1, unsigned char);
+ memcpy(buffer, *start, len);
+ buffer[len] = '\0';
+ {
+ unsigned char *p = buffer;
+
+ while (p < buffer+len && *p == ' ') p++;
+ /*
+ * Warning message from virtual font.
+ */
+ if (!memcmp((char *)p, "Warning:", 8)) {
+ if (dpx_conf.verbose_level > 0)
+ WARN("VF:%s", p+8);
+ } else {
+ dvi_do_special(buffer, len);
+ }
+ }
+ RELEASE(buffer);
+ } else {
+ ERROR ("Premature end of DVI byte stream in VF font.");
+ }
+
+ *start += len;
+ return;
+}
+
+void vf_set_char(int32_t ch, int vf_font)
+{
+ unsigned char opcode;
+ unsigned char *start, *end;
+ spt_t ptsize;
+ int default_font = -1;
+ if (vf_font < num_vf_fonts) {
+ /* Initialize to the first font or -1 if undefined */
+ ptsize = vf_fonts[vf_font].ptsize;
+ if (vf_fonts[vf_font].num_dev_fonts > 0)
+ default_font = ((vf_fonts[vf_font].dev_fonts)[0]).dev_id;
+ dvi_vf_init (default_font);
+ if (ch >= vf_fonts[vf_font].num_chars ||
+ !(start = (vf_fonts[vf_font].ch_pkt)[ch])) {
+ if (tfm_is_jfm(vf_fonts[vf_font].dev_fonts[0].tfm_id) &&
+ ch < 0x1000000 && dpx_conf.compat_mode != dpx_mode_xdv_mode) {
+ /* fallback multibyte character for (u)pTeX */
+ if (dpx_conf.verbose_level == 1)
+ if (vf_fonts[vf_font].message_flag == 0) {
+ WARN ("Fallback multibyte character in virtual font: VF:%s to TFM:%s",
+ vf_fonts[vf_font].tex_name, vf_fonts[vf_font].dev_fonts[0].name);
+ vf_fonts[vf_font].message_flag = 1;
+ }
+ if (dpx_conf.verbose_level > 1)
+ WARN ("Fallback multibyte character in virtual font: VF:%s char=0x%06x(%d) to TFM:%s",
+ vf_fonts[vf_font].tex_name, ch, ch, vf_fonts[vf_font].dev_fonts[0].name);
+ dvi_set (ch);
+ dvi_vf_finish();
+ return;
+ }
+ fprintf (stderr, "\nchar=0x%x(%d)\n", ch, ch);
+ fprintf (stderr, "Tried to set a nonexistent character in a virtual font");
+ start = end = NULL;
+ } else {
+ end = start + (vf_fonts[vf_font].pkt_len)[ch];
+ }
+ while (start && start < end) {
+ opcode = *(start++);
+#ifdef DEBUG
+ fprintf (stderr, "VF opcode: %d", opcode);
+ if (isprint (opcode)) fprintf (stderr, " (\'%c\')\n", opcode);
+ else fprintf (stderr, "\n");
+#endif
+ switch (opcode)
+ {
+ case SET1: case SET2: case SET3:
+ dvi_set (get_pkt_unsigned_num (&start, end, opcode-SET1));
+ break;
+ case SET4:
+ ERROR ("Multibyte (>24 bits) character in VF packet.\nI can't handle this!");
+ break;
+ case SET_RULE:
+ vf_setrule(&start, end, ptsize);
+ break;
+ case PUT1: case PUT2: case PUT3:
+ dvi_put (get_pkt_unsigned_num (&start, end, opcode-PUT1));
+ break;
+ case PUT4:
+ ERROR ("Multibyte (>24 bits) character in VF packet.\nI can't handle this!");
+ break;
+ case PUT_RULE:
+ vf_putrule(&start, end, ptsize);
+ break;
+ case NOP:
+ break;
+ case PUSH:
+ dvi_push();
+ break;
+ case POP:
+ dvi_pop();
+ break;
+ case RIGHT1: case RIGHT2: case RIGHT3: case RIGHT4:
+ dvi_right (sqxfw (ptsize, get_pkt_signed_num (&start, end, opcode-RIGHT1)));
+ break;
+ case W0:
+ dvi_w0();
+ break;
+ case W1: case W2: case W3: case W4:
+ dvi_w (sqxfw (ptsize, get_pkt_signed_num (&start, end, opcode-W1)));
+ break;
+ case X0:
+ dvi_x0();
+ break;
+ case X1: case X2: case X3: case X4:
+ dvi_x (sqxfw (ptsize, get_pkt_signed_num (&start, end, opcode-X1)));
+ break;
+ case DOWN1: case DOWN2: case DOWN3: case DOWN4:
+ dvi_down (sqxfw (ptsize, get_pkt_signed_num (&start, end, opcode-DOWN1)));
+ break;
+ case Y0:
+ dvi_y0();
+ break;
+ case Y1: case Y2: case Y3: case Y4:
+ dvi_y (sqxfw (ptsize, get_pkt_signed_num (&start, end, opcode-Y1)));
+ break;
+ case Z0:
+ dvi_z0();
+ break;
+ case Z1: case Z2: case Z3: case Z4:
+ dvi_z (sqxfw (ptsize, get_pkt_signed_num (&start, end, opcode-Z1)));
+ break;
+ case FNT1: case FNT2: case FNT3: case FNT4:
+ vf_fnt (get_pkt_signed_num (&start, end, opcode-FNT1), vf_font);
+ break;
+ case XXX1: case XXX2: case XXX3: case XXX4:
+ {
+ int32_t len = get_pkt_unsigned_num (&start, end, opcode-XXX1);
+ if (len < 0)
+ WARN("VF: Special with %d bytes???", len);
+ else
+ vf_xxx (len, &start, end);
+ }
+ break;
+ case PTEXDIR:
+ dvi_dirchg (unsigned_byte (&start, end));
+ break;
+ default:
+ if (opcode <= SET_CHAR_127) {
+ dvi_set (opcode);
+ } else if (opcode >= FNT_NUM_0 && opcode <= FNT_NUM_63) {
+ vf_fnt (opcode - FNT_NUM_0, vf_font);
+ } else {
+ fprintf (stderr, "Unexpected opcode: %d\n", opcode);
+ ERROR ("Unexpected opcode in vf file\n");
+ }
+ }
+ }
+ dvi_vf_finish();
+ } else {
+ fprintf (stderr, "vf_set_char: font: %d", vf_font);
+ ERROR ("Font not loaded\n");
+ }
+ return;
+}
+
+
+void vf_close_all_fonts(void)
+{
+ int i;
+ int j;
+ struct font_def *one_font;
+ for (i=0; i<num_vf_fonts; i++) {
+ /* Release the packet for each character */
+ if (vf_fonts[i].ch_pkt) {
+ for (j=0; j<vf_fonts[i].num_chars; j++) {
+ if ((vf_fonts[i].ch_pkt)[j] != NULL)
+ RELEASE ((vf_fonts[i].ch_pkt)[j]);
+ }
+ RELEASE (vf_fonts[i].ch_pkt);
+ }
+ if (vf_fonts[i].pkt_len)
+ RELEASE (vf_fonts[i].pkt_len);
+ if (vf_fonts[i].tex_name)
+ RELEASE (vf_fonts[i].tex_name);
+ /* Release each font record */
+ for (j=0; j<vf_fonts[i].num_dev_fonts; j++) {
+ one_font = &(vf_fonts[i].dev_fonts)[j];
+ RELEASE (one_font -> directory);
+ RELEASE (one_font -> name);
+ }
+ if (vf_fonts[i].dev_fonts != NULL)
+ RELEASE (vf_fonts[i].dev_fonts);
+ }
+ if (vf_fonts != NULL)
+ RELEASE (vf_fonts);
+ return;
+}
+#if defined(LIBDPX)
+#include "vf_ng.c"
+#endif /* LIBDPX */