OSDN Git Service

update.
[putex/putex.git] / src / dvipdfmx-pu / src / pkfont.c
1 /*  
2
3     This is dvipdfmx, an eXtended version of dvipdfm by Mark A. Wicks.
4
5     Copyright (C) 2007-2012 by Jin-Hwan Cho and Shunsaku Hirata,
6     the dvipdfmx project team.
7     
8     Copyright (C) 1998, 1999 by Mark A. Wicks <mwicks@kettering.edu>
9
10     This program is free software; you can redistribute it and/or modify
11     it under the terms of the GNU General Public License as published by
12     the Free Software Foundation; either version 2 of the License, or
13     (at your option) any later version.
14     
15     This program is distributed in the hope that it will be useful,
16     but WITHOUT ANY WARRANTY; without even the implied warranty of
17     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18     GNU General Public License for more details.
19     
20     You should have received a copy of the GNU General Public License
21     along with this program; if not, write to the Free Software
22     Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
23 */
24
25 #if HAVE_CONFIG_H
26 #include "config.h"
27 #endif
28
29 #include "system.h"
30 #include "mem.h"
31 #include "error.h"
32
33 #include "dpxfile.h"
34
35 #include "numbers.h"
36 #include "pdfobj.h"
37 #include "pdfdev.h" /* pdf_rect */
38
39 #include "pdfencoding.h"
40 #include "pdffont.h"
41
42 #include "pkfont.h"
43
44 #define ENABLE_GLYPHENC  1
45
46 #ifndef PKFONT_DPI_DEFAULT
47 #define PKFONT_DPI_DEFAULT 600u
48 #endif
49
50 static unsigned base_dpi = PKFONT_DPI_DEFAULT;
51
52 void
53 PKFont_set_dpi (int dpi)
54 {
55   if (dpi <= 0)
56     ERROR("Invalid DPI: %d\n", dpi);
57   base_dpi = dpi;
58 }
59
60
61 /* (Only) This requires TFM to get design size... */
62 #include "tfm.h"
63
64 static unsigned
65 truedpi (const char *ident, double point_size, unsigned bdpi)
66 {
67   unsigned  dpi = bdpi;
68   double    design_size;
69   int       tfm_id;
70
71   tfm_id = tfm_open(ident, 0);
72   if (tfm_id < 0)
73     return  dpi;
74
75   design_size = tfm_get_design_size(tfm_id);
76   if (design_size <= 0.0)
77     WARN("DESGIN_SIZE <= 0.0? (TFM=\"%s\")", ident);
78   else {
79     dpi  = (unsigned) ROUND(base_dpi * point_size / design_size, 1.0);
80   }
81
82   return  dpi;
83 }
84
85 static FILE *
86 dpx_open_pk_font_at (const char *ident, unsigned dpi)
87 {
88   FILE  *fp;
89   char  *fqpn;
90   kpse_glyph_file_type kpse_file_info;
91
92   fqpn = kpse_find_glyph(ident, dpi, kpse_pk_format, &kpse_file_info);
93   if (!fqpn)
94     return  NULL;
95   fp   = MFOPEN(fqpn, FOPEN_RBIN_MODE);
96   RELEASE(fqpn);
97
98   return  fp;
99 }
100
101
102 int
103 pdf_font_open_pkfont (pdf_font *font)
104 {
105   char     *ident;
106   double    point_size;
107   int       encoding_id;
108   unsigned  dpi;
109   FILE     *fp;
110
111   ident       = pdf_font_get_ident(font);
112   point_size  = pdf_font_get_param(font, PDF_FONT_PARAM_POINT_SIZE);
113   encoding_id = pdf_font_get_encoding(font);
114
115   if (!ident || point_size <= 0.0)
116     return  -1;
117
118   dpi = truedpi(ident, point_size, base_dpi);
119   fp  = dpx_open_pk_font_at(ident, dpi);
120   if (!fp)
121     return  -1;
122   MFCLOSE(fp);
123
124   /* Type 3 fonts doesn't have FontName.
125    * FontFamily is recommended for PDF 1.5.
126    */
127   pdf_font_set_fontname(font, ident);
128
129   if (encoding_id >= 0) {
130     pdf_encoding_used_by_type3(encoding_id);
131     WARN("PK font is found for font \"%s\" but non built-in encoding \"%s\" is specified.",
132          ident, pdf_encoding_get_name(encoding_id));
133 #if  ENABLE_GLYPHENC
134     WARN(">> Assuming this is for glyph name assignment.");
135 #else
136     WARN(">> I can't reencode PK font. (not enough information available)");
137     WARN(">> Maybe you need to install pfb/opentype/truetype font.");
138 #endif
139   }
140
141   return  0;
142 }
143
144
145 /* We are using Mask Image. Fill black is bit clear.
146  * Optimizing those codes doesn't improve things.
147  */
148 static long
149 fill_black_run (unsigned char *dp, long left, long run_count)
150 {
151   const static unsigned char mask[8] = {
152     127u, 191u, 223u, 239u, 247u, 251u, 253u, 254u
153   };
154   long  right = left + run_count - 1;
155   for ( ; left <= right; left++) {
156     dp[left / 8] &= mask[left % 8];
157   }
158   return  run_count;
159 }
160
161 /* Just skip bits. See decode_packed() */
162 static long
163 fill_white_run (unsigned char *dp, long left, long run_count)
164 {
165   return  run_count;
166 }
167
168 static long
169 pk_packed_num (long *np, int dyn_f, unsigned char *dp, long pl)
170 {
171   long  nmbr = 0, i = *np;
172   int   nyb, j;
173 #define get_nyb() ((i % 2) ? dp[i/2] & 0x0f : (dp[i/2] >> 4) & 0x0f)
174
175   if (i / 2 == pl) {
176     WARN("EOD reached while unpacking pk_packed_num.");
177     return  0;
178   }
179   nyb = get_nyb(); i++;
180   if (nyb == 0) {
181     j = 0;
182     do {
183       if (i / 2 == pl) {
184         WARN("EOD reached while unpacking pk_packed_num.");
185         break;
186       }
187       nyb = get_nyb(); i++;
188       j++;
189     } while (nyb == 0);
190     nmbr = nyb;
191     while (j-- > 0) {
192       if (i / 2 == pl) {
193         WARN("EOD reached while unpacking pk_packed_num.");
194         break;
195       }
196       nyb  = get_nyb(); i++;
197       nmbr = nmbr * 16 + nyb;
198     }
199     nmbr += (13 - dyn_f) * 16 + dyn_f - 15;
200   } else if (nyb <= dyn_f) {
201     nmbr = nyb;
202   } else if (nyb < 14) {
203     if (i / 2 == pl) {
204       WARN("EOD reached while unpacking pk_packed_num.");
205       return  0;
206     }
207     nmbr = (nyb - dyn_f - 1) * 16 + get_nyb() + dyn_f + 1;
208     i++;
209   }
210
211   *np = i;
212   return  nmbr;
213 }
214
215
216 #if  DEBUG == 2
217 static void
218 send_out (unsigned char *rowptr, long rowbytes, long  wd, pdf_obj *stream)
219 #else
220 static void
221 send_out (unsigned char *rowptr, long rowbytes, pdf_obj *stream)
222 #endif
223 {
224   pdf_add_stream(stream, (void *)rowptr, rowbytes);
225 #if  DEBUG == 2
226   {
227     long  i, n, len = (wd + 7) / 8;
228     int   c;
229     fputc('|', stderr);
230     for (n = 0; n < len; n++) {
231       c = rowptr[n];
232       for (i = 0; i < 8; i++) {
233         if (n * 8 + i == wd)
234           break;
235         if (c & 1 << (7 - i))
236           fputc(' ', stderr);
237         else
238           fputc('*', stderr);
239       }
240     }
241     fputc('|', stderr);
242     fputc('\n', stderr);
243   }
244 #endif /* DEBUG2 */
245 }
246
247 static int
248 pk_decode_packed (pdf_obj *stream, long wd, long ht,
249                   int dyn_f, int run_color, unsigned char *dp, long pl)
250 {
251   unsigned char  *rowptr;
252   long            rowbytes;
253   long            i, np = 0;
254   long            run_count = 0, repeat_count = 0;
255
256   rowbytes = (wd + 7) / 8;
257   rowptr   = NEW(rowbytes, unsigned char);
258   /* repeat count is applied to the *current* row.
259    * "run" can span across rows.
260    * If there are non-zero repeat count and if run
261    * spans across row, first repeat and then continue.
262    */
263 #ifdef  DEBUG
264   MESG("\npkfont>> wd: %ld, ht: %ld, dyn_f: %d\n", wd, ht, dyn_f);
265 #endif
266   for (np = 0, i = 0; i < ht; i++) {
267     long  rowbits_left, nbits;
268
269     repeat_count = 0;
270     memset(rowptr, 0xff, rowbytes); /* 1 is white */
271     rowbits_left = wd;
272     /* Fill run left over from previous row */
273     if (run_count > 0) {
274       nbits = MIN(rowbits_left, run_count);
275       switch (run_color) {
276       case  0:
277         rowbits_left -= fill_black_run(rowptr, 0, nbits);
278         break;
279       case  1:
280         rowbits_left -= fill_white_run(rowptr, 0, nbits);
281         break;
282       }
283       run_count -= nbits;
284     }
285
286     /* Read nybbles until we have a full row */
287     while (np / 2 < pl && rowbits_left > 0) {
288       int  nyb;
289
290       nyb = (np % 2) ? dp[np/2] & 0x0f : (dp[np/2] >> 4) & 0x0f;
291 #if  DEBUG == 3
292       MESG("\npk_nyb: %d", nyb);
293 #endif
294       if (nyb == 14) { /* packed number "repeat_count" follows */
295         if (repeat_count != 0)
296           WARN("Second repeat count for this row!");
297         np++; /* Consume this nybble */
298         repeat_count = pk_packed_num(&np, dyn_f, dp, pl);
299 #if  DEBUG == 3
300         MESG(" --> rep: %ld\n", repeat_count);
301 #endif
302       } else if (nyb == 15) {
303         if (repeat_count != 0)
304           WARN("Second repeat count for this row!");
305         np++; /* Consume this nybble */
306         repeat_count = 1;
307 #if  DEBUG == 3
308         MESG(" --> rep: %ld\n", repeat_count);
309 #endif
310       } else { /* run_count */
311         /* Interprete current nybble as packed number */
312         run_count = pk_packed_num(&np, dyn_f, dp, pl);
313 #if  DEBUG == 3
314         MESG(" --> run: %ld (%d)\n", run_count, run_color);
315 #endif
316         nbits = MIN(rowbits_left, run_count);
317         run_color  = !run_color;
318         run_count -= nbits;
319         switch (run_color) {
320         case  0:
321           rowbits_left -= fill_black_run(rowptr, wd - rowbits_left, nbits);
322           break;
323         case  1:
324           rowbits_left -= fill_white_run(rowptr, wd - rowbits_left, nbits);
325           break;
326         }
327       }
328     }
329     /* We got bitmap row data. */
330 #if  DEBUG == 2
331     send_out(rowptr, rowbytes, wd, stream);
332 #else
333     send_out(rowptr, rowbytes, stream);
334 #endif
335     for ( ; i < ht && repeat_count > 0; repeat_count--, i++)
336 #if  DEBUG == 2
337       send_out(rowptr, rowbytes, wd, stream);
338 #else
339     send_out(rowptr, rowbytes, stream);
340 #endif
341   }
342   RELEASE(rowptr);
343
344   return  0;
345 }
346
347 static int
348 pk_decode_bitmap (pdf_obj *stream, long wd, long ht,
349                   int dyn_f, int run_color, unsigned char *dp, long pl)
350 {
351   unsigned char  *rowptr, c;
352   long            i, j, rowbytes;
353   const static unsigned char mask[8] = {
354     0x80u, 0x40u, 0x20u, 0x10u, 0x08u, 0x04u, 0x02u, 0x01u
355   };
356
357   ASSERT( dyn_f == 14 );
358   if (run_color != 0) {
359     WARN("run_color != 0 for bitmap pk data?");
360   } else if (pl < (wd * ht + 7) / 8) {
361     WARN("Insufficient bitmap pk data. %ldbytes expected but only %ldbytes read.",
362          (wd * ht + 7) / 8, pl);
363     return  -1;
364   }
365
366   rowbytes = (wd + 7) / 8;
367   rowptr   = NEW(rowbytes, unsigned char);
368   memset(rowptr, 0, rowbytes);
369   /* Flip. PK bitmap is not byte aligned for each rows. */
370   for (i = 0, j = 0; i < ht * wd; i++) {
371     c = dp[i / 8] & mask[i % 8];
372     if (c == 0)
373       rowptr[j / 8] |= mask[i % 8]; /* flip bit */
374     j++;
375     if (j == wd) {
376 #if  DEBUG == 2
377       send_out(rowptr, rowbytes, wd, stream);
378 #else
379       send_out(rowptr, rowbytes, stream);
380 #endif
381       memset(rowptr, 0, rowbytes);
382       j = 0;
383     }
384   }
385
386   return  0;
387 }
388
389
390 /* Read PK font file */
391 static void
392 do_skip (FILE *fp, unsigned long length) 
393 {
394   while (length-- > 0)
395     fgetc(fp);
396 }
397
398 static void
399 do_preamble (FILE *fp)
400 {
401   /* Check for id byte */
402   if (fgetc(fp) == 89) {
403     /* Skip comment */
404     do_skip(fp, get_unsigned_byte(fp));
405     /* Skip other header info.  It's normally used for verifying this
406        is the file wethink it is */
407     do_skip(fp, 16);
408   } else {
409     ERROR("embed_pk_font: PK ID byte is incorrect.  Are you sure this is a PK file?");
410   }
411   return;
412 }
413
414 struct pk_header_
415 {
416   unsigned long  pkt_len;
417   SIGNED_QUAD    chrcode;
418   SIGNED_QUAD    wd, dx, dy;
419   SIGNED_QUAD    bm_wd, bm_ht, bm_hoff, bm_voff;
420   int            dyn_f, run_color;
421 };
422
423 static int
424 read_pk_char_header (struct pk_header_ *h, unsigned char opcode, FILE *fp)
425 {
426   ASSERT(h);
427
428   if ((opcode & 4) == 0) { /* short */
429     h->pkt_len = (opcode & 3) * 0x100U + get_unsigned_byte(fp);
430     h->chrcode = get_unsigned_byte(fp);
431     h->wd = get_unsigned_triple(fp);     /* TFM width */
432     h->dx = get_unsigned_byte(fp) << 16; /* horizontal escapement */
433     h->dy = 0L;
434     h->bm_wd    = get_unsigned_byte(fp);
435     h->bm_ht    = get_unsigned_byte(fp);
436     h->bm_hoff  = get_signed_byte(fp);
437     h->bm_voff  = get_signed_byte(fp);
438     h->pkt_len -= 8;
439   } else if ((opcode & 7) == 7) { /* long */
440     h->pkt_len = get_unsigned_quad(fp);
441     h->chrcode = get_signed_quad(fp);
442     h->wd = get_signed_quad(fp);
443     h->dx = get_signed_quad(fp); /* 16.16 fixed point number in pixels */
444     h->dy = get_signed_quad(fp);
445     h->bm_wd    = get_signed_quad(fp);
446     h->bm_ht    = get_signed_quad(fp);
447     h->bm_hoff  = get_signed_quad(fp);
448     h->bm_voff  = get_signed_quad(fp);
449     h->pkt_len -= 28;
450   } else { /* extended short */
451     h->pkt_len = (opcode & 3) * 0x10000UL + get_unsigned_pair(fp);
452     h->chrcode = get_unsigned_byte(fp);
453     h->wd = get_unsigned_triple(fp);
454     h->dx = get_unsigned_pair(fp) << 16;
455     h->dy = 0x0L;
456     h->bm_wd    = get_unsigned_pair(fp);
457     h->bm_ht    = get_unsigned_pair(fp);
458     h->bm_hoff  = get_signed_pair(fp);
459     h->bm_voff  = get_signed_pair(fp);
460     h->pkt_len -= 13;
461   }
462
463   h->dyn_f     = opcode / 16;
464   h->run_color = (opcode & 8) ? 1 : 0;
465
466   if (h->chrcode > 0xff)
467   {
468     WARN("Unable to handle long characters in PK files: code=0x%04x", h->chrcode);
469     return  -1;
470   }
471
472   return  0;
473 }
474
475 /* CCITT Group 4 filter may reduce file size. */
476 static pdf_obj *
477 create_pk_CharProc_stream (struct pk_header_ *pkh,
478                            double             chrwid,
479                            unsigned char     *pkt_ptr, long pkt_len)
480 {
481   pdf_obj  *stream; /* charproc */
482   long      llx, lly, urx, ury;
483   int       len;
484
485   llx = -pkh->bm_hoff;
486   lly =  pkh->bm_voff - pkh->bm_ht;
487   urx =  pkh->bm_wd - pkh->bm_hoff;
488   ury =  pkh->bm_voff;
489
490   stream = pdf_new_stream(STREAM_COMPRESS);
491   /*
492    * The following line is a "metric" for the PDF reader:
493    *
494    * PDF Reference Reference, 4th ed., p.385.
495    *
496    * The wx (first operand of d1) must be consistent with the corresponding
497    * width in the font's Widths array. The format string of sprint() must be
498    * consistent with write_number() in pdfobj.c.
499    */
500   len = pdf_sprint_number(work_buffer, chrwid);
501   len += sprintf (work_buffer + len, " 0 %ld %ld %ld %ld d1\n", llx, lly, urx, ury);
502   pdf_add_stream(stream, work_buffer, len);
503   /*
504    * Acrobat dislike transformation [0 0 0 0 dx dy].
505    * PDF Reference, 4th ed., p.147, says,
506    *
507    *   Use of a noninvertible matrix when painting graphics objects can result in
508    *   unpredictable behavior.
509    *
510    * but it does not forbid use of such transformation.
511    */
512   if (pkh->bm_wd != 0 && pkh->bm_ht != 0 && pkt_len > 0) {
513     /* Scale and translate origin to lower left corner for raster data */
514     len = sprintf (work_buffer, "q\n%ld 0 0 %ld %ld %ld cm\n", pkh->bm_wd, pkh->bm_ht, llx, lly);
515     pdf_add_stream(stream, work_buffer, len);
516     len = sprintf (work_buffer, "BI\n/W %ld\n/H %ld\n/IM true\n/BPC 1\nID ", pkh->bm_wd, pkh->bm_ht);
517     pdf_add_stream(stream, work_buffer, len);
518     /* Add bitmap data */
519     if (pkh->dyn_f == 14) /* bitmap */
520               pk_decode_bitmap(stream,
521                                pkh->bm_wd, pkh->bm_ht,
522                                pkh->dyn_f, pkh->run_color,
523                                pkt_ptr,    pkt_len);
524     else
525               pk_decode_packed(stream,
526                                pkh->bm_wd, pkh->bm_ht,
527                                pkh->dyn_f, pkh->run_color,
528                                pkt_ptr,    pkt_len);
529     len = sprintf (work_buffer, "\nEI\nQ");
530     pdf_add_stream(stream, work_buffer, len);
531   } /* Otherwise we embed an empty stream :-( */
532
533   return  stream;
534 }
535
536 #define PK_XXX1  240
537 #define PK_XXX2  241
538 #define PK_XXX3  242
539 #define PK_XXX4  243
540 #define PK_YYY   244
541 #define PK_POST  245
542 #define PK_NO_OP 246
543 #define PK_PRE   247
544
545 #define pk_char2name(b,c) sprintf((b), "x%02X", (unsigned char)(c))
546 int
547 pdf_font_load_pkfont (pdf_font *font)
548 {
549   pdf_obj  *fontdict;
550   char     *usedchars;
551   char     *ident;
552   unsigned  dpi;
553   FILE     *fp;
554   double    point_size, pix2charu;
555   int       opcode, code, firstchar, lastchar, prev;
556   pdf_obj  *charprocs, *procset, *encoding, *tmp_array;
557   double    widths[256];
558   pdf_rect  bbox;
559   char      charavail[256];
560 #if  ENABLE_GLYPHENC
561   int       encoding_id;
562   char    **enc_vec;
563 #endif /* ENABLE_GLYPHENC */
564   int       error = 0;
565
566   if (!pdf_font_is_in_use(font)) {
567     return 0;
568   }
569
570   ident       = pdf_font_get_ident(font);
571   point_size  = pdf_font_get_param(font, PDF_FONT_PARAM_POINT_SIZE);
572   usedchars   = pdf_font_get_usedchars(font);
573 #if  ENABLE_GLYPHENC
574   encoding_id = pdf_font_get_encoding(font);
575   if (encoding_id < 0)
576     enc_vec = NULL;
577   else {
578     enc_vec = pdf_encoding_get_encoding(encoding_id);
579   }
580 #endif /* ENABLE_GLYPHENC */
581
582   ASSERT(ident && usedchars && point_size > 0.0);
583
584   dpi  = truedpi(ident, point_size, base_dpi);
585   fp   = dpx_open_pk_font_at(ident, dpi);
586   if (!fp) {
587     ERROR("Could not find/open PK font file: %s (at %udpi)", ident, dpi);
588   }
589
590   memset(charavail, 0, 256);
591   charprocs  = pdf_new_dict();
592   /* Include bitmap as 72dpi image:
593    * There seems to be problems in "scaled" bitmap glyph
594    * rendering in several viewers.
595    */
596   pix2charu  = 72. * 1000. / ((double) base_dpi) / point_size;
597   bbox.llx = bbox.lly =  HUGE_VAL;
598   bbox.urx = bbox.ury = -HUGE_VAL;
599   while ((opcode = fgetc(fp)) >= 0 && opcode != PK_POST) {
600     if (opcode < 240) {
601       struct pk_header_  pkh;
602
603       error = read_pk_char_header(&pkh, opcode, fp);
604       if (error)
605         ERROR("Error in reading PK character header.");
606       else if (charavail[pkh.chrcode & 0xff])
607         WARN("More than two bitmap image for single glyph?: font=\"%s\" code=0x%02x",
608              ident, pkh.chrcode);
609
610       if (!usedchars[pkh.chrcode & 0xff])
611         do_skip(fp, pkh.pkt_len);
612       else {
613         char          *charname;
614         pdf_obj       *charproc;
615         unsigned char *pkt_ptr;
616         size_t         bytesread;
617         double         charwidth;
618
619         /* Charwidth in PDF units */
620         charwidth = ROUND(1000.0 * pkh.wd / (((double) (1<<20))*pix2charu), 0.1);
621         widths[pkh.chrcode & 0xff] = charwidth;
622
623         /* Update font BBox info */
624         bbox.llx = MIN(bbox.llx, -pkh.bm_hoff);
625         bbox.lly = MIN(bbox.lly,  pkh.bm_voff - pkh.bm_ht);
626         bbox.urx = MAX(bbox.urx,  pkh.bm_wd - pkh.bm_hoff);
627         bbox.ury = MAX(bbox.ury,  pkh.bm_voff);
628
629         pkt_ptr = NEW(pkh.pkt_len, unsigned char);
630         if ((bytesread = fread(pkt_ptr, 1, pkh.pkt_len, fp))!= pkh.pkt_len) {
631           ERROR("Only %ld bytes PK packet read. (expected %ld bytes)",
632                 bytesread, pkh.pkt_len);
633         }
634         charproc = create_pk_CharProc_stream(&pkh, charwidth, pkt_ptr, bytesread);
635         RELEASE(pkt_ptr);
636         if (!charproc)
637           ERROR("Unpacking PK character data failed.");
638 #if  ENABLE_GLYPHENC
639         if (encoding_id >= 0 && enc_vec) {
640           charname = (char *) enc_vec[pkh.chrcode & 0xff];
641           if (!charname) {
642             WARN("\".notdef\" glyph used in font (code=0x%02x): %s", pkh.chrcode, ident);
643             charname = work_buffer;
644             pk_char2name(charname, pkh.chrcode);
645           }
646         }
647         else
648 #endif /* ENABLE_GLYPHENC */
649         {
650           charname = work_buffer;
651           pk_char2name(charname, pkh.chrcode);
652         }
653
654         pdf_add_dict(charprocs, pdf_new_name(charname), pdf_ref_obj(charproc)); /* _FIXME_ */
655         pdf_release_obj(charproc);
656       }
657       charavail[pkh.chrcode & 0xff] = 1;
658     } else { /* A command byte */
659       switch (opcode) {
660       case PK_NO_OP: break;
661       case PK_XXX1: do_skip(fp, get_unsigned_byte(fp));   break;
662       case PK_XXX2: do_skip(fp, get_unsigned_pair(fp));   break;
663       case PK_XXX3: do_skip(fp, get_unsigned_triple(fp)); break;
664       case PK_XXX4: do_skip(fp, get_unsigned_quad(fp));   break;
665       case PK_YYY:  do_skip(fp, 4);  break;
666       case PK_PRE:  do_preamble(fp); break;
667       }
668     }
669   }
670   MFCLOSE(fp);
671
672   /* Check if we really got all glyphs needed. */
673   for (code = 0; code < 256; code++) {
674     if (usedchars[code] && !charavail[code])
675       WARN("Missing glyph code=0x%02x in PK font \"%s\".", code, ident);
676   }
677
678   /* Now actually fill fontdict. */
679   fontdict = pdf_font_get_resource(font);
680
681   pdf_add_dict(fontdict,
682                pdf_new_name("CharProcs"), pdf_ref_obj(charprocs));
683   pdf_release_obj(charprocs);
684
685   /*
686    * Resources:
687    *
688    *  PDF Reference 4th ed. describes it as "Optional but strongly recommended".
689    *  There are no reason to put it in our case, but we will put this.
690    *  We do not care about compatibility with Acrobat 2.x. (See implementation
691    *  note 47, Appendix H of PDF Ref., 4th ed.).
692    */
693   procset   = pdf_new_dict();
694   tmp_array = pdf_new_array();
695   pdf_add_array(tmp_array, pdf_new_name("PDF"));
696   pdf_add_array(tmp_array, pdf_new_name("ImageB"));
697   pdf_add_dict(procset,
698                pdf_new_name("ProcSet"), tmp_array);
699   pdf_add_dict(fontdict,
700                pdf_new_name("Resources"), procset);
701
702   /* Encoding */
703   tmp_array = pdf_new_array();
704   prev = -2; firstchar = 255; lastchar = 0;
705   for (code = 0; code < 256; code++) {
706     char  *charname;
707     if (usedchars[code]) {
708       if (code < firstchar) firstchar = code;
709       if (code > lastchar)  lastchar  = code;
710       if (code != prev + 1)
711         pdf_add_array(tmp_array, pdf_new_number(code));
712
713 #if  ENABLE_GLYPHENC
714       if (encoding_id >= 0 && enc_vec) {
715         charname = (char *) enc_vec[(unsigned char) code];
716         if (!charname) {
717           charname = work_buffer;
718           pk_char2name(charname, code);
719         }
720       }
721       else
722 #endif /* ENABLE_GLYPHENC */
723       {
724         charname = work_buffer;
725         pk_char2name(charname, code);
726       }
727       pdf_add_array(tmp_array, pdf_new_name(charname));
728       prev = code;
729     }
730   }
731   if (firstchar > lastchar) {
732     ERROR("Unexpected error: firstchar > lastchar (%d %d)",
733           firstchar, lastchar);
734     pdf_release_obj(tmp_array);
735     return  -1;
736   }
737 #if  ENABLE_GLYPHENC
738   if (encoding_id < 0 || !enc_vec) {
739 #else
740   if (1) {
741 #endif /* ENABLE_GLYPHENC */
742     encoding  = pdf_new_dict();
743     pdf_add_dict(encoding,
744                  pdf_new_name("Type"), pdf_new_name("Encoding"));
745     pdf_add_dict(encoding,
746                  pdf_new_name("Differences"), tmp_array);
747     pdf_add_dict(fontdict,
748                  pdf_new_name("Encoding"),    pdf_ref_obj(encoding));
749     pdf_release_obj(encoding);
750   } else
751     pdf_release_obj(tmp_array);
752
753   /* FontBBox: Accurate value is important.
754    */
755   tmp_array = pdf_new_array();
756   pdf_add_array(tmp_array, pdf_new_number(bbox.llx));
757   pdf_add_array(tmp_array, pdf_new_number(bbox.lly));
758   pdf_add_array(tmp_array, pdf_new_number(bbox.urx));
759   pdf_add_array(tmp_array, pdf_new_number(bbox.ury));
760   pdf_add_dict (fontdict , pdf_new_name("FontBBox"), tmp_array);
761
762   /* Widths:
763    *  Indirect reference preffered. (See PDF Reference)
764    */
765   tmp_array = pdf_new_array();
766   for (code = firstchar; code <= lastchar; code++) {
767     if (usedchars[code])
768       pdf_add_array(tmp_array, pdf_new_number(widths[code]));
769     else {
770       pdf_add_array(tmp_array, pdf_new_number(0));
771     }
772   }
773   pdf_add_dict(fontdict,
774                pdf_new_name("Widths"), pdf_ref_obj(tmp_array));
775   pdf_release_obj(tmp_array);
776
777   /* FontMatrix */
778   tmp_array = pdf_new_array();
779   pdf_add_array(tmp_array, pdf_new_number(0.001 * pix2charu));
780   pdf_add_array(tmp_array, pdf_new_number(0.0));
781   pdf_add_array(tmp_array, pdf_new_number(0.0));
782   pdf_add_array(tmp_array, pdf_new_number(0.001 * pix2charu));
783   pdf_add_array(tmp_array, pdf_new_number(0.0));
784   pdf_add_array(tmp_array, pdf_new_number(0.0));
785   pdf_add_dict (fontdict , pdf_new_name("FontMatrix"), tmp_array);
786
787
788   pdf_add_dict(fontdict,
789                pdf_new_name("FirstChar"), pdf_new_number(firstchar));
790   pdf_add_dict(fontdict,
791                pdf_new_name("LastChar"),  pdf_new_number(lastchar));
792
793   return  0;
794 }