diff options
Diffstat (limited to 'Build/source/texk/dvipdfm-x/pkfont.c')
-rw-r--r-- | Build/source/texk/dvipdfm-x/pkfont.c | 794 |
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; +} |