summaryrefslogtreecommitdiff
path: root/Build/source/texk/dvipdfm-x/pkfont.c
diff options
context:
space:
mode:
Diffstat (limited to 'Build/source/texk/dvipdfm-x/pkfont.c')
-rw-r--r--Build/source/texk/dvipdfm-x/pkfont.c794
1 files changed, 794 insertions, 0 deletions
diff --git a/Build/source/texk/dvipdfm-x/pkfont.c b/Build/source/texk/dvipdfm-x/pkfont.c
new file mode 100644
index 00000000000..12ba5b76fae
--- /dev/null
+++ b/Build/source/texk/dvipdfm-x/pkfont.c
@@ -0,0 +1,794 @@
+/*
+
+ This is dvipdfmx, an eXtended version of dvipdfm by Mark A. Wicks.
+
+ Copyright (C) 2007-2012 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.
+*/
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "system.h"
+#include "mem.h"
+#include "error.h"
+
+#include "dpxfile.h"
+
+#include "numbers.h"
+#include "pdfobj.h"
+#include "pdfdev.h" /* pdf_rect */
+
+#include "pdfencoding.h"
+#include "pdffont.h"
+
+#include "pkfont.h"
+
+#define ENABLE_GLYPHENC 1
+
+#ifndef PKFONT_DPI_DEFAULT
+#define PKFONT_DPI_DEFAULT 600u
+#endif
+
+static unsigned base_dpi = PKFONT_DPI_DEFAULT;
+
+void
+PKFont_set_dpi (int dpi)
+{
+ if (dpi <= 0)
+ ERROR("Invalid DPI: %d\n", dpi);
+ base_dpi = dpi;
+}
+
+
+/* (Only) This requires TFM to get design size... */
+#include "tfm.h"
+
+static unsigned
+truedpi (const char *ident, double point_size, unsigned bdpi)
+{
+ unsigned dpi = bdpi;
+ double design_size;
+ int tfm_id;
+
+ tfm_id = tfm_open(ident, 0);
+ if (tfm_id < 0)
+ return dpi;
+
+ design_size = tfm_get_design_size(tfm_id);
+ if (design_size <= 0.0)
+ WARN("DESGIN_SIZE <= 0.0? (TFM=\"%s\")", ident);
+ else {
+ dpi = (unsigned) ROUND(base_dpi * point_size / design_size, 1.0);
+ }
+
+ return dpi;
+}
+
+static FILE *
+dpx_open_pk_font_at (const char *ident, unsigned dpi)
+{
+ FILE *fp;
+ char *fqpn;
+ kpse_glyph_file_type kpse_file_info;
+
+ fqpn = kpse_find_glyph(ident, dpi, kpse_pk_format, &kpse_file_info);
+ if (!fqpn)
+ return NULL;
+ fp = MFOPEN(fqpn, FOPEN_RBIN_MODE);
+ RELEASE(fqpn);
+
+ return fp;
+}
+
+
+int
+pdf_font_open_pkfont (pdf_font *font)
+{
+ char *ident;
+ double point_size;
+ int encoding_id;
+ unsigned dpi;
+ FILE *fp;
+
+ ident = pdf_font_get_ident(font);
+ point_size = pdf_font_get_param(font, PDF_FONT_PARAM_POINT_SIZE);
+ encoding_id = pdf_font_get_encoding(font);
+
+ if (!ident || point_size <= 0.0)
+ return -1;
+
+ dpi = truedpi(ident, point_size, base_dpi);
+ fp = dpx_open_pk_font_at(ident, dpi);
+ if (!fp)
+ return -1;
+ MFCLOSE(fp);
+
+ /* Type 3 fonts doesn't have FontName.
+ * FontFamily is recommended for PDF 1.5.
+ */
+ pdf_font_set_fontname(font, ident);
+
+ if (encoding_id >= 0) {
+ pdf_encoding_used_by_type3(encoding_id);
+ WARN("PK font is found for font \"%s\" but non built-in encoding \"%s\" is specified.",
+ ident, pdf_encoding_get_name(encoding_id));
+#if ENABLE_GLYPHENC
+ WARN(">> Assuming this is for glyph name assignment.");
+#else
+ WARN(">> I can't reencode PK font. (not enough information available)");
+ WARN(">> Maybe you need to install pfb/opentype/truetype font.");
+#endif
+ }
+
+ return 0;
+}
+
+
+/* We are using Mask Image. Fill black is bit clear.
+ * Optimizing those codes doesn't improve things.
+ */
+static long
+fill_black_run (unsigned char *dp, long left, long run_count)
+{
+ const static unsigned char mask[8] = {
+ 127u, 191u, 223u, 239u, 247u, 251u, 253u, 254u
+ };
+ long right = left + run_count - 1;
+ for ( ; left <= right; left++) {
+ dp[left / 8] &= mask[left % 8];
+ }
+ return run_count;
+}
+
+/* Just skip bits. See decode_packed() */
+static long
+fill_white_run (unsigned char *dp, long left, long run_count)
+{
+ return run_count;
+}
+
+static long
+pk_packed_num (long *np, int dyn_f, unsigned char *dp, long pl)
+{
+ long nmbr = 0, i = *np;
+ int nyb, j;
+#define get_nyb() ((i % 2) ? dp[i/2] & 0x0f : (dp[i/2] >> 4) & 0x0f)
+
+ if (i / 2 == pl) {
+ WARN("EOD reached while unpacking pk_packed_num.");
+ return 0;
+ }
+ nyb = get_nyb(); i++;
+ if (nyb == 0) {
+ j = 0;
+ do {
+ if (i / 2 == pl) {
+ WARN("EOD reached while unpacking pk_packed_num.");
+ break;
+ }
+ nyb = get_nyb(); i++;
+ j++;
+ } while (nyb == 0);
+ nmbr = nyb;
+ while (j-- > 0) {
+ if (i / 2 == pl) {
+ WARN("EOD reached while unpacking pk_packed_num.");
+ break;
+ }
+ nyb = get_nyb(); i++;
+ nmbr = nmbr * 16 + nyb;
+ }
+ nmbr += (13 - dyn_f) * 16 + dyn_f - 15;
+ } else if (nyb <= dyn_f) {
+ nmbr = nyb;
+ } else if (nyb < 14) {
+ if (i / 2 == pl) {
+ WARN("EOD reached while unpacking pk_packed_num.");
+ return 0;
+ }
+ nmbr = (nyb - dyn_f - 1) * 16 + get_nyb() + dyn_f + 1;
+ i++;
+ }
+
+ *np = i;
+ return nmbr;
+}
+
+
+#if DEBUG == 2
+static void
+send_out (unsigned char *rowptr, long rowbytes, long wd, pdf_obj *stream)
+#else
+static void
+send_out (unsigned char *rowptr, long rowbytes, pdf_obj *stream)
+#endif
+{
+ pdf_add_stream(stream, (void *)rowptr, rowbytes);
+#if DEBUG == 2
+ {
+ long i, n, len = (wd + 7) / 8;
+ int c;
+ fputc('|', stderr);
+ for (n = 0; n < len; n++) {
+ c = rowptr[n];
+ for (i = 0; i < 8; i++) {
+ if (n * 8 + i == wd)
+ break;
+ if (c & 1 << (7 - i))
+ fputc(' ', stderr);
+ else
+ fputc('*', stderr);
+ }
+ }
+ fputc('|', stderr);
+ fputc('\n', stderr);
+ }
+#endif /* DEBUG2 */
+}
+
+static int
+pk_decode_packed (pdf_obj *stream, long wd, long ht,
+ int dyn_f, int run_color, unsigned char *dp, long pl)
+{
+ unsigned char *rowptr;
+ long rowbytes;
+ long i, np = 0;
+ long run_count = 0, repeat_count = 0;
+
+ rowbytes = (wd + 7) / 8;
+ rowptr = NEW(rowbytes, unsigned char);
+ /* repeat count is applied to the *current* row.
+ * "run" can span across rows.
+ * If there are non-zero repeat count and if run
+ * spans across row, first repeat and then continue.
+ */
+#ifdef DEBUG
+ MESG("\npkfont>> wd: %ld, ht: %ld, dyn_f: %d\n", wd, ht, dyn_f);
+#endif
+ for (np = 0, i = 0; i < ht; i++) {
+ long rowbits_left, nbits;
+
+ repeat_count = 0;
+ memset(rowptr, 0xff, rowbytes); /* 1 is white */
+ rowbits_left = wd;
+ /* Fill run left over from previous row */
+ if (run_count > 0) {
+ nbits = MIN(rowbits_left, run_count);
+ switch (run_color) {
+ case 0:
+ rowbits_left -= fill_black_run(rowptr, 0, nbits);
+ break;
+ case 1:
+ rowbits_left -= fill_white_run(rowptr, 0, nbits);
+ break;
+ }
+ run_count -= nbits;
+ }
+
+ /* Read nybbles until we have a full row */
+ while (np / 2 < pl && rowbits_left > 0) {
+ int nyb;
+
+ nyb = (np % 2) ? dp[np/2] & 0x0f : (dp[np/2] >> 4) & 0x0f;
+#if DEBUG == 3
+ MESG("\npk_nyb: %d", nyb);
+#endif
+ if (nyb == 14) { /* packed number "repeat_count" follows */
+ if (repeat_count != 0)
+ WARN("Second repeat count for this row!");
+ np++; /* Consume this nybble */
+ repeat_count = pk_packed_num(&np, dyn_f, dp, pl);
+#if DEBUG == 3
+ MESG(" --> rep: %ld\n", repeat_count);
+#endif
+ } else if (nyb == 15) {
+ if (repeat_count != 0)
+ WARN("Second repeat count for this row!");
+ np++; /* Consume this nybble */
+ repeat_count = 1;
+#if DEBUG == 3
+ MESG(" --> rep: %ld\n", repeat_count);
+#endif
+ } else { /* run_count */
+ /* Interprete current nybble as packed number */
+ run_count = pk_packed_num(&np, dyn_f, dp, pl);
+#if DEBUG == 3
+ MESG(" --> run: %ld (%d)\n", run_count, run_color);
+#endif
+ nbits = MIN(rowbits_left, run_count);
+ run_color = !run_color;
+ run_count -= nbits;
+ switch (run_color) {
+ case 0:
+ rowbits_left -= fill_black_run(rowptr, wd - rowbits_left, nbits);
+ break;
+ case 1:
+ rowbits_left -= fill_white_run(rowptr, wd - rowbits_left, nbits);
+ break;
+ }
+ }
+ }
+ /* We got bitmap row data. */
+#if DEBUG == 2
+ send_out(rowptr, rowbytes, wd, stream);
+#else
+ send_out(rowptr, rowbytes, stream);
+#endif
+ for ( ; i < ht && repeat_count > 0; repeat_count--, i++)
+#if DEBUG == 2
+ send_out(rowptr, rowbytes, wd, stream);
+#else
+ send_out(rowptr, rowbytes, stream);
+#endif
+ }
+ RELEASE(rowptr);
+
+ return 0;
+}
+
+static int
+pk_decode_bitmap (pdf_obj *stream, long wd, long ht,
+ int dyn_f, int run_color, unsigned char *dp, long pl)
+{
+ unsigned char *rowptr, c;
+ long i, j, rowbytes;
+ const static unsigned char mask[8] = {
+ 0x80u, 0x40u, 0x20u, 0x10u, 0x08u, 0x04u, 0x02u, 0x01u
+ };
+
+ ASSERT( dyn_f == 14 );
+ if (run_color != 0) {
+ WARN("run_color != 0 for bitmap pk data?");
+ } else if (pl < (wd * ht + 7) / 8) {
+ WARN("Insufficient bitmap pk data. %ldbytes expected but only %ldbytes read.",
+ (wd * ht + 7) / 8, pl);
+ return -1;
+ }
+
+ rowbytes = (wd + 7) / 8;
+ rowptr = NEW(rowbytes, unsigned char);
+ memset(rowptr, 0, rowbytes);
+ /* Flip. PK bitmap is not byte aligned for each rows. */
+ for (i = 0, j = 0; i < ht * wd; i++) {
+ c = dp[i / 8] & mask[i % 8];
+ if (c == 0)
+ rowptr[j / 8] |= mask[i % 8]; /* flip bit */
+ j++;
+ if (j == wd) {
+#if DEBUG == 2
+ send_out(rowptr, rowbytes, wd, stream);
+#else
+ send_out(rowptr, rowbytes, stream);
+#endif
+ memset(rowptr, 0, rowbytes);
+ j = 0;
+ }
+ }
+
+ return 0;
+}
+
+
+/* Read PK font file */
+static void
+do_skip (FILE *fp, unsigned long length)
+{
+ while (length-- > 0)
+ fgetc(fp);
+}
+
+static void
+do_preamble (FILE *fp)
+{
+ /* Check for id byte */
+ if (fgetc(fp) == 89) {
+ /* Skip comment */
+ do_skip(fp, get_unsigned_byte(fp));
+ /* Skip other header info. It's normally used for verifying this
+ is the file wethink it is */
+ do_skip(fp, 16);
+ } else {
+ ERROR("embed_pk_font: PK ID byte is incorrect. Are you sure this is a PK file?");
+ }
+ return;
+}
+
+struct pk_header_
+{
+ unsigned long pkt_len;
+ SIGNED_QUAD chrcode;
+ SIGNED_QUAD wd, dx, dy;
+ SIGNED_QUAD bm_wd, bm_ht, bm_hoff, bm_voff;
+ int dyn_f, run_color;
+};
+
+static int
+read_pk_char_header (struct pk_header_ *h, unsigned char opcode, FILE *fp)
+{
+ ASSERT(h);
+
+ if ((opcode & 4) == 0) { /* short */
+ h->pkt_len = (opcode & 3) * 0x100U + get_unsigned_byte(fp);
+ h->chrcode = get_unsigned_byte(fp);
+ h->wd = get_unsigned_triple(fp); /* TFM width */
+ h->dx = get_unsigned_byte(fp) << 16; /* horizontal escapement */
+ h->dy = 0L;
+ h->bm_wd = get_unsigned_byte(fp);
+ h->bm_ht = get_unsigned_byte(fp);
+ h->bm_hoff = get_signed_byte(fp);
+ h->bm_voff = get_signed_byte(fp);
+ h->pkt_len -= 8;
+ } else if ((opcode & 7) == 7) { /* long */
+ h->pkt_len = get_unsigned_quad(fp);
+ h->chrcode = get_signed_quad(fp);
+ h->wd = get_signed_quad(fp);
+ h->dx = get_signed_quad(fp); /* 16.16 fixed point number in pixels */
+ h->dy = get_signed_quad(fp);
+ h->bm_wd = get_signed_quad(fp);
+ h->bm_ht = get_signed_quad(fp);
+ h->bm_hoff = get_signed_quad(fp);
+ h->bm_voff = get_signed_quad(fp);
+ h->pkt_len -= 28;
+ } else { /* extended short */
+ h->pkt_len = (opcode & 3) * 0x10000UL + get_unsigned_pair(fp);
+ h->chrcode = get_unsigned_byte(fp);
+ h->wd = get_unsigned_triple(fp);
+ h->dx = get_unsigned_pair(fp) << 16;
+ h->dy = 0x0L;
+ h->bm_wd = get_unsigned_pair(fp);
+ h->bm_ht = get_unsigned_pair(fp);
+ h->bm_hoff = get_signed_pair(fp);
+ h->bm_voff = get_signed_pair(fp);
+ h->pkt_len -= 13;
+ }
+
+ h->dyn_f = opcode / 16;
+ h->run_color = (opcode & 8) ? 1 : 0;
+
+ if (h->chrcode > 0xff)
+ {
+ WARN("Unable to handle long characters in PK files: code=0x%04x", h->chrcode);
+ return -1;
+ }
+
+ return 0;
+}
+
+/* CCITT Group 4 filter may reduce file size. */
+static pdf_obj *
+create_pk_CharProc_stream (struct pk_header_ *pkh,
+ double chrwid,
+ unsigned char *pkt_ptr, long pkt_len)
+{
+ pdf_obj *stream; /* charproc */
+ long llx, lly, urx, ury;
+ int len;
+
+ llx = -pkh->bm_hoff;
+ lly = pkh->bm_voff - pkh->bm_ht;
+ urx = pkh->bm_wd - pkh->bm_hoff;
+ ury = pkh->bm_voff;
+
+ stream = pdf_new_stream(STREAM_COMPRESS);
+ /*
+ * The following line is a "metric" for the PDF reader:
+ *
+ * PDF Reference Reference, 4th ed., p.385.
+ *
+ * The wx (first operand of d1) must be consistent with the corresponding
+ * width in the font's Widths array. The format string of sprint() must be
+ * consistent with write_number() in pdfobj.c.
+ */
+ len = pdf_sprint_number(work_buffer, chrwid);
+ len += sprintf (work_buffer + len, " 0 %ld %ld %ld %ld d1\n", llx, lly, urx, ury);
+ pdf_add_stream(stream, work_buffer, len);
+ /*
+ * Acrobat dislike transformation [0 0 0 0 dx dy].
+ * PDF Reference, 4th ed., p.147, says,
+ *
+ * Use of a noninvertible matrix when painting graphics objects can result in
+ * unpredictable behavior.
+ *
+ * but it does not forbid use of such transformation.
+ */
+ if (pkh->bm_wd != 0 && pkh->bm_ht != 0 && pkt_len > 0) {
+ /* Scale and translate origin to lower left corner for raster data */
+ len = sprintf (work_buffer, "q\n%ld 0 0 %ld %ld %ld cm\n", pkh->bm_wd, pkh->bm_ht, llx, lly);
+ pdf_add_stream(stream, work_buffer, len);
+ len = sprintf (work_buffer, "BI\n/W %ld\n/H %ld\n/IM true\n/BPC 1\nID ", pkh->bm_wd, pkh->bm_ht);
+ pdf_add_stream(stream, work_buffer, len);
+ /* Add bitmap data */
+ if (pkh->dyn_f == 14) /* bitmap */
+ pk_decode_bitmap(stream,
+ pkh->bm_wd, pkh->bm_ht,
+ pkh->dyn_f, pkh->run_color,
+ pkt_ptr, pkt_len);
+ else
+ pk_decode_packed(stream,
+ pkh->bm_wd, pkh->bm_ht,
+ pkh->dyn_f, pkh->run_color,
+ pkt_ptr, pkt_len);
+ len = sprintf (work_buffer, "\nEI\nQ");
+ pdf_add_stream(stream, work_buffer, len);
+ } /* Otherwise we embed an empty stream :-( */
+
+ return stream;
+}
+
+#define PK_XXX1 240
+#define PK_XXX2 241
+#define PK_XXX3 242
+#define PK_XXX4 243
+#define PK_YYY 244
+#define PK_POST 245
+#define PK_NO_OP 246
+#define PK_PRE 247
+
+#define pk_char2name(b,c) sprintf((b), "x%02X", (unsigned char)(c))
+int
+pdf_font_load_pkfont (pdf_font *font)
+{
+ pdf_obj *fontdict;
+ char *usedchars;
+ char *ident;
+ unsigned dpi;
+ FILE *fp;
+ double point_size, pix2charu;
+ int opcode, code, firstchar, lastchar, prev;
+ pdf_obj *charprocs, *procset, *encoding, *tmp_array;
+ double widths[256];
+ pdf_rect bbox;
+ char charavail[256];
+#if ENABLE_GLYPHENC
+ int encoding_id;
+ char **enc_vec;
+#endif /* ENABLE_GLYPHENC */
+ int error = 0;
+
+ if (!pdf_font_is_in_use(font)) {
+ return 0;
+ }
+
+ ident = pdf_font_get_ident(font);
+ point_size = pdf_font_get_param(font, PDF_FONT_PARAM_POINT_SIZE);
+ usedchars = pdf_font_get_usedchars(font);
+#if ENABLE_GLYPHENC
+ encoding_id = pdf_font_get_encoding(font);
+ if (encoding_id < 0)
+ enc_vec = NULL;
+ else {
+ enc_vec = pdf_encoding_get_encoding(encoding_id);
+ }
+#endif /* ENABLE_GLYPHENC */
+
+ ASSERT(ident && usedchars && point_size > 0.0);
+
+ dpi = truedpi(ident, point_size, base_dpi);
+ fp = dpx_open_pk_font_at(ident, dpi);
+ if (!fp) {
+ ERROR("Could not find/open PK font file: %s (at %udpi)", ident, dpi);
+ }
+
+ memset(charavail, 0, 256);
+ charprocs = pdf_new_dict();
+ /* Include bitmap as 72dpi image:
+ * There seems to be problems in "scaled" bitmap glyph
+ * rendering in several viewers.
+ */
+ pix2charu = 72. * 1000. / ((double) base_dpi) / point_size;
+ bbox.llx = bbox.lly = HUGE_VAL;
+ bbox.urx = bbox.ury = -HUGE_VAL;
+ while ((opcode = fgetc(fp)) >= 0 && opcode != PK_POST) {
+ if (opcode < 240) {
+ struct pk_header_ pkh;
+
+ error = read_pk_char_header(&pkh, opcode, fp);
+ if (error)
+ ERROR("Error in reading PK character header.");
+ else if (charavail[pkh.chrcode & 0xff])
+ WARN("More than two bitmap image for single glyph?: font=\"%s\" code=0x%02x",
+ ident, pkh.chrcode);
+
+ if (!usedchars[pkh.chrcode & 0xff])
+ do_skip(fp, pkh.pkt_len);
+ else {
+ char *charname;
+ pdf_obj *charproc;
+ unsigned char *pkt_ptr;
+ size_t bytesread;
+ double charwidth;
+
+ /* Charwidth in PDF units */
+ charwidth = ROUND(1000.0 * pkh.wd / (((double) (1<<20))*pix2charu), 0.1);
+ widths[pkh.chrcode & 0xff] = charwidth;
+
+ /* Update font BBox info */
+ bbox.llx = MIN(bbox.llx, -pkh.bm_hoff);
+ bbox.lly = MIN(bbox.lly, pkh.bm_voff - pkh.bm_ht);
+ bbox.urx = MAX(bbox.urx, pkh.bm_wd - pkh.bm_hoff);
+ bbox.ury = MAX(bbox.ury, pkh.bm_voff);
+
+ pkt_ptr = NEW(pkh.pkt_len, unsigned char);
+ if ((bytesread = fread(pkt_ptr, 1, pkh.pkt_len, fp))!= pkh.pkt_len) {
+ ERROR("Only %ld bytes PK packet read. (expected %ld bytes)",
+ bytesread, pkh.pkt_len);
+ }
+ charproc = create_pk_CharProc_stream(&pkh, charwidth, pkt_ptr, bytesread);
+ RELEASE(pkt_ptr);
+ if (!charproc)
+ ERROR("Unpacking PK character data failed.");
+#if ENABLE_GLYPHENC
+ if (encoding_id >= 0 && enc_vec) {
+ charname = (char *) enc_vec[pkh.chrcode & 0xff];
+ if (!charname) {
+ WARN("\".notdef\" glyph used in font (code=0x%02x): %s", pkh.chrcode, ident);
+ charname = work_buffer;
+ pk_char2name(charname, pkh.chrcode);
+ }
+ }
+ else
+#endif /* ENABLE_GLYPHENC */
+ {
+ charname = work_buffer;
+ pk_char2name(charname, pkh.chrcode);
+ }
+
+ pdf_add_dict(charprocs, pdf_new_name(charname), pdf_ref_obj(charproc)); /* _FIXME_ */
+ pdf_release_obj(charproc);
+ }
+ charavail[pkh.chrcode & 0xff] = 1;
+ } else { /* A command byte */
+ switch (opcode) {
+ case PK_NO_OP: break;
+ case PK_XXX1: do_skip(fp, get_unsigned_byte(fp)); break;
+ case PK_XXX2: do_skip(fp, get_unsigned_pair(fp)); break;
+ case PK_XXX3: do_skip(fp, get_unsigned_triple(fp)); break;
+ case PK_XXX4: do_skip(fp, get_unsigned_quad(fp)); break;
+ case PK_YYY: do_skip(fp, 4); break;
+ case PK_PRE: do_preamble(fp); break;
+ }
+ }
+ }
+ MFCLOSE(fp);
+
+ /* Check if we really got all glyphs needed. */
+ for (code = 0; code < 256; code++) {
+ if (usedchars[code] && !charavail[code])
+ WARN("Missing glyph code=0x%02x in PK font \"%s\".", code, ident);
+ }
+
+ /* Now actually fill fontdict. */
+ fontdict = pdf_font_get_resource(font);
+
+ pdf_add_dict(fontdict,
+ pdf_new_name("CharProcs"), pdf_ref_obj(charprocs));
+ pdf_release_obj(charprocs);
+
+ /*
+ * Resources:
+ *
+ * PDF Reference 4th ed. describes it as "Optional but strongly recommended".
+ * There are no reason to put it in our case, but we will put this.
+ * We do not care about compatibility with Acrobat 2.x. (See implementation
+ * note 47, Appendix H of PDF Ref., 4th ed.).
+ */
+ procset = pdf_new_dict();
+ tmp_array = pdf_new_array();
+ pdf_add_array(tmp_array, pdf_new_name("PDF"));
+ pdf_add_array(tmp_array, pdf_new_name("ImageB"));
+ pdf_add_dict(procset,
+ pdf_new_name("ProcSet"), tmp_array);
+ pdf_add_dict(fontdict,
+ pdf_new_name("Resources"), procset);
+
+ /* Encoding */
+ tmp_array = pdf_new_array();
+ prev = -2; firstchar = 255; lastchar = 0;
+ for (code = 0; code < 256; code++) {
+ char *charname;
+ if (usedchars[code]) {
+ if (code < firstchar) firstchar = code;
+ if (code > lastchar) lastchar = code;
+ if (code != prev + 1)
+ pdf_add_array(tmp_array, pdf_new_number(code));
+
+#if ENABLE_GLYPHENC
+ if (encoding_id >= 0 && enc_vec) {
+ charname = (char *) enc_vec[(unsigned char) code];
+ if (!charname) {
+ charname = work_buffer;
+ pk_char2name(charname, code);
+ }
+ }
+ else
+#endif /* ENABLE_GLYPHENC */
+ {
+ charname = work_buffer;
+ pk_char2name(charname, code);
+ }
+ pdf_add_array(tmp_array, pdf_new_name(charname));
+ prev = code;
+ }
+ }
+ if (firstchar > lastchar) {
+ ERROR("Unexpected error: firstchar > lastchar (%d %d)",
+ firstchar, lastchar);
+ pdf_release_obj(tmp_array);
+ return -1;
+ }
+#if ENABLE_GLYPHENC
+ if (encoding_id < 0 || !enc_vec) {
+#else
+ if (1) {
+#endif /* ENABLE_GLYPHENC */
+ encoding = pdf_new_dict();
+ pdf_add_dict(encoding,
+ pdf_new_name("Type"), pdf_new_name("Encoding"));
+ pdf_add_dict(encoding,
+ pdf_new_name("Differences"), tmp_array);
+ pdf_add_dict(fontdict,
+ pdf_new_name("Encoding"), pdf_ref_obj(encoding));
+ pdf_release_obj(encoding);
+ } else
+ pdf_release_obj(tmp_array);
+
+ /* FontBBox: Accurate value is important.
+ */
+ tmp_array = pdf_new_array();
+ pdf_add_array(tmp_array, pdf_new_number(bbox.llx));
+ pdf_add_array(tmp_array, pdf_new_number(bbox.lly));
+ pdf_add_array(tmp_array, pdf_new_number(bbox.urx));
+ pdf_add_array(tmp_array, pdf_new_number(bbox.ury));
+ pdf_add_dict (fontdict , pdf_new_name("FontBBox"), tmp_array);
+
+ /* Widths:
+ * Indirect reference preffered. (See PDF Reference)
+ */
+ tmp_array = pdf_new_array();
+ for (code = firstchar; code <= lastchar; code++) {
+ if (usedchars[code])
+ pdf_add_array(tmp_array, pdf_new_number(widths[code]));
+ else {
+ pdf_add_array(tmp_array, pdf_new_number(0));
+ }
+ }
+ pdf_add_dict(fontdict,
+ pdf_new_name("Widths"), pdf_ref_obj(tmp_array));
+ pdf_release_obj(tmp_array);
+
+ /* FontMatrix */
+ tmp_array = pdf_new_array();
+ pdf_add_array(tmp_array, pdf_new_number(0.001 * pix2charu));
+ pdf_add_array(tmp_array, pdf_new_number(0.0));
+ pdf_add_array(tmp_array, pdf_new_number(0.0));
+ pdf_add_array(tmp_array, pdf_new_number(0.001 * pix2charu));
+ pdf_add_array(tmp_array, pdf_new_number(0.0));
+ pdf_add_array(tmp_array, pdf_new_number(0.0));
+ pdf_add_dict (fontdict , pdf_new_name("FontMatrix"), tmp_array);
+
+
+ pdf_add_dict(fontdict,
+ pdf_new_name("FirstChar"), pdf_new_number(firstchar));
+ pdf_add_dict(fontdict,
+ pdf_new_name("LastChar"), pdf_new_number(lastchar));
+
+ return 0;
+}