1 /* This is dvipdfmx, an eXtended version of dvipdfm by Mark A. Wicks.
2 
3     Copyright (C) 2008-2014 by Jin-Hwan Cho, Matthias Franz, and Shunsaku Hirata,
4     the dvipdfmx project team.
5 
6     Copyright (C) 1998, 1999 by Mark A. Wicks <mwicks@kettering.edu>
7 
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.
12 
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.
17 
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.
21 */
22 
23 #ifdef HAVE_CONFIG_H
24 #include <config.h>
25 #endif
26 
27 #include <string.h>
28 #include <time.h>
29 
30 #include "system.h"
31 #include "error.h"
32 #include "mem.h"
33 
34 #include "dpxfile.h"
35 #include "dpxutil.h"
36 
37 #include "pdfobj.h"
38 
39 #include "agl.h"
40 #include "pdfencoding.h"
41 #include "cmap.h"
42 #include "unicode.h"
43 
44 #include "type1.h"
45 #include "type1c.h"
46 #include "truetype.h"
47 
48 #include "pkfont.h"
49 
50 #include "type0.h"
51 #include "tt_cmap.h"
52 #include "cidtype0.h"
53 #include "otl_conf.h"
54 
55 #include "pdffont.h"
56 
57 static int __verbose = 0;
58 
59 #define MREC_HAS_TOUNICODE(m) ((m) && (m)->opt.tounicode)
60 
61 void
pdf_font_set_verbose(void)62 pdf_font_set_verbose (void)
63 {
64   __verbose++;
65   CMap_set_verbose();
66   Type0Font_set_verbose();
67   CIDFont_set_verbose  ();
68   pdf_encoding_set_verbose();
69   UC_set_verbose ();
70   agl_set_verbose();
71   otl_conf_set_verbose();
72   otf_cmap_set_verbose ();
73 }
74 
75 int
pdf_font_get_verbose(void)76 pdf_font_get_verbose (void)
77 {
78   return __verbose;
79 }
80 
81 void
pdf_font_set_dpi(int font_dpi)82 pdf_font_set_dpi (int font_dpi)
83 {
84   PKFont_set_dpi(font_dpi);
85 }
86 
87 void
pdf_font_make_uniqueTag(char * tag)88 pdf_font_make_uniqueTag (char *tag)
89 {
90   int    i;
91   char   ch;
92   static char first = 1;
93 
94   if (first) {
95     srand(time(NULL));
96     first = 0;
97   }
98 
99   for (i = 0; i < 6; i++) {
100     ch = rand() % 26;
101     tag[i] = ch + 'A';
102   }
103   tag[6] = '\0';
104 }
105 
106 
107 struct pdf_font
108 {
109   char    *ident;
110   int      subtype;
111 
112   char    *map_name;
113 
114   int      encoding_id; /* encoding or CMap */
115 
116   /*
117    * If subtype is Type0, it simply points font_id
118    * of Type0 font. Type0 and simple font is not
119    * unified yet.
120    */
121   int      font_id;
122 
123   /* For simple font */
124   int      index;
125   char    *fontname;
126   char     uniqueID[7];
127 
128   /*
129    * PDF font resource objects
130    */
131   pdf_obj *reference;
132   pdf_obj *resource;
133   pdf_obj *descriptor;
134 
135   /*
136    * Font format specific data
137    */
138   char    *usedchars;
139   int      flags;
140 
141   /* PK font */
142   double   point_size;
143   double   design_size;
144 };
145 
146 static void
pdf_init_font_struct(pdf_font * font)147 pdf_init_font_struct (pdf_font *font)
148 {
149   ASSERT(font);
150 
151   font->ident    = NULL;
152   font->map_name = NULL;
153   font->subtype  = -1;
154   font->font_id  = -1; /* Type0 ID */
155   font->fontname = NULL;
156   memset(font->uniqueID, 0, 7);
157   font->index    = 0;
158 
159   font->encoding_id = -1;
160 
161   font->reference   = NULL;
162   font->resource    = NULL;
163   font->descriptor  = NULL;
164 
165   font->point_size  = 0;
166   font->design_size = 0;
167 
168   font->usedchars   = NULL;
169   font->flags       = 0;
170 
171   return;
172 }
173 
174 static void
pdf_flush_font(pdf_font * font)175 pdf_flush_font (pdf_font *font)
176 {
177   char *fontname, *uniqueTag;
178 
179   if (!font) {
180     return;
181   }
182 
183   if (font->resource && font->reference) {
184     if (font->subtype != PDF_FONT_FONTTYPE_TYPE3) {
185       if (pdf_font_get_flag(font, PDF_FONT_FLAG_NOEMBED)) {
186 	pdf_add_dict(font->resource,
187 		     pdf_new_name("BaseFont"), pdf_new_name(font->fontname));
188 	if (font->descriptor) {
189 	  pdf_add_dict(font->descriptor,
190 		       pdf_new_name("FontName"), pdf_new_name(font->fontname));
191 	}
192       } else {
193 	if (!font->fontname) {
194 	  ERROR("Undefined in fontname... (%s)", font->ident);
195 	}
196 	fontname  = NEW(7+strlen(font->fontname)+1, char);
197 	uniqueTag = pdf_font_get_uniqueTag(font);
198 	sprintf(fontname, "%6s+%s", uniqueTag, font->fontname);
199 	pdf_add_dict(font->resource,
200 		     pdf_new_name("BaseFont"), pdf_new_name(fontname));
201 	if (font->descriptor) {
202 	  pdf_add_dict(font->descriptor,
203 		       pdf_new_name("FontName"), pdf_new_name(fontname));
204 	}
205 	RELEASE(fontname);
206       }
207       if (font->descriptor) {
208 	pdf_add_dict(font->resource,
209 		     pdf_new_name("FontDescriptor"), pdf_ref_obj(font->descriptor));
210       }
211     }
212   }
213 
214   if (font->resource)
215     pdf_release_obj(font->resource);
216   if (font->descriptor)
217     pdf_release_obj(font->descriptor);
218   if (font->reference)
219     pdf_release_obj(font->reference);
220 
221   font->reference  = NULL;
222   font->resource   = NULL;
223   font->descriptor = NULL;
224 
225   return;
226 }
227 
228 static void
pdf_clean_font_struct(pdf_font * font)229 pdf_clean_font_struct (pdf_font *font)
230 {
231   if (font) {
232     if (font->ident)
233       RELEASE(font->ident);
234     if (font->map_name)
235       RELEASE(font->map_name);
236     if (font->fontname)
237       RELEASE(font->fontname);
238     if (font->usedchars)
239       RELEASE(font->usedchars);
240 
241     if (font->reference)
242       ERROR("pdf_font>> Object not flushed.");
243     if (font->resource)
244       ERROR("pdf_font> Object not flushed.");
245     if (font->descriptor)
246       ERROR("pdf_font>> Object not flushed.");
247 
248     font->ident     = NULL;
249     font->map_name  = NULL;
250     font->fontname  = NULL;
251     font->usedchars = NULL;
252   }
253 
254   return;
255 }
256 
257 #define CACHE_ALLOC_SIZE 16u
258 
259 static struct {
260   int       count;
261   int       capacity;
262   pdf_font *fonts;
263 } font_cache = {
264   0, 0, NULL
265 };
266 
267 void
pdf_init_fonts(void)268 pdf_init_fonts (void)
269 {
270   ASSERT(font_cache.fonts == NULL);
271 
272   agl_init_map();
273   otl_init_conf();
274 
275   CMap_cache_init();
276   pdf_init_encodings();
277 
278   Type0Font_cache_init();
279 
280   font_cache.count    = 0;
281   font_cache.capacity = CACHE_ALLOC_SIZE;
282   font_cache.fonts    = NEW(font_cache.capacity, pdf_font);
283 }
284 
285 #define CHECK_ID(n) do {\
286   if ((n) < 0 || (n) >= font_cache.count) {\
287     ERROR("Invalid font ID: %d", (n));\
288   }\
289 } while (0)
290 #define GET_FONT(n)  (&(font_cache.fonts[(n)]))
291 
292 
293 pdf_obj *
pdf_get_font_reference(int font_id)294 pdf_get_font_reference (int font_id)
295 {
296   pdf_font  *font;
297 
298   CHECK_ID(font_id);
299 
300   font = GET_FONT(font_id);
301   if (font->subtype == PDF_FONT_FONTTYPE_TYPE0) {
302     Type0Font *t0font;
303 
304     t0font = Type0Font_cache_get(font->font_id);
305     return Type0Font_get_resource(t0font);
306   } else {
307     if (!font->reference) {
308       font->reference = pdf_ref_obj(pdf_font_get_resource(font));
309     }
310   }
311 
312   return pdf_link_obj(font->reference);
313 }
314 
315 char *
pdf_get_font_usedchars(int font_id)316 pdf_get_font_usedchars (int font_id)
317 {
318   pdf_font *font;
319 
320   CHECK_ID(font_id);
321 
322   font = GET_FONT(font_id);
323   if (font->subtype == PDF_FONT_FONTTYPE_TYPE0) {
324     Type0Font *t0font;
325 
326     t0font = Type0Font_cache_get(font->font_id);
327     return Type0Font_get_usedchars(t0font);
328   } else {
329     if (!font->usedchars) {
330       font->usedchars = NEW(256, char);
331       memset(font->usedchars, 0, 256 * sizeof(char));
332     }
333     return font->usedchars;
334   }
335 }
336 
337 int
pdf_get_font_wmode(int font_id)338 pdf_get_font_wmode (int font_id)
339 {
340   pdf_font *font;
341 
342   CHECK_ID(font_id);
343 
344   font = GET_FONT(font_id);
345   if (font->subtype == PDF_FONT_FONTTYPE_TYPE0) {
346     Type0Font *t0font;
347 
348     t0font = Type0Font_cache_get(font->font_id);
349     return Type0Font_get_wmode(t0font);
350   } else {
351     return 0;
352   }
353 }
354 
355 int
pdf_get_font_subtype(int font_id)356 pdf_get_font_subtype (int font_id)
357 {
358   pdf_font *font;
359 
360   CHECK_ID(font_id);
361 
362   font = GET_FONT(font_id);
363 
364   return font->subtype;
365 }
366 
367 #if 0
368 char *
369 pdf_get_font_fontname (int font_id)
370 {
371   pdf_font *font;
372 
373   CHECK_ID(font_id);
374 
375   font = GET_FONT(font_id);
376 
377   return font->fontname;
378 }
379 #endif /* 0 */
380 
381 int
pdf_get_font_encoding(int font_id)382 pdf_get_font_encoding (int font_id)
383 {
384   pdf_font *font;
385 
386   CHECK_ID(font_id);
387 
388   font = GET_FONT(font_id);
389 
390   return font->encoding_id;
391 }
392 
393 /* The rule for ToUnicode creation is:
394  *
395  *  If "tounicode" option is specified in fontmap, use that.
396  *  If there is ToUnicode CMap with same name as TFM, use that.
397  *  If no "tounicode" option is used and no ToUnicode CMap with
398  *  same name as TFM is found, create ToUnicode CMap from glyph
399  *  names and AGL file.
400  */
401 static int
try_load_ToUnicode_CMap(pdf_font * font)402 try_load_ToUnicode_CMap (pdf_font *font)
403 {
404   pdf_obj     *fontdict;
405   pdf_obj     *tounicode;
406   const char  *cmap_name = NULL;
407   fontmap_rec *mrec; /* Be sure fontmap is still alive here */
408 
409   ASSERT(font);
410 
411   /* We are using different encoding for Type0 font.
412    * This feature is unavailable for them.
413    */
414   if (font->subtype == PDF_FONT_FONTTYPE_TYPE0)
415     return  0;
416 
417   ASSERT(font->map_name);
418 
419   mrec = pdf_lookup_fontmap_record(font->map_name);
420   if (MREC_HAS_TOUNICODE(mrec))
421     cmap_name = mrec->opt.tounicode;
422   else {
423     cmap_name = font->map_name;
424   }
425 
426   fontdict  = pdf_font_get_resource(font);
427   tounicode = pdf_load_ToUnicode_stream(cmap_name);
428   if (!tounicode && MREC_HAS_TOUNICODE(mrec))
429     WARN("Failed to read ToUnicode mapping \"%s\"...", mrec->opt.tounicode);
430   else if (tounicode) {
431     if (pdf_obj_typeof(tounicode) != PDF_STREAM)
432       ERROR("Object returned by pdf_load_ToUnicode_stream() not stream object! (This must be bug)");
433     else if (pdf_stream_length(tounicode) > 0) {
434       pdf_add_dict(fontdict,
435                    pdf_new_name("ToUnicode"),
436                    pdf_ref_obj (tounicode)); /* _FIXME_ */
437       if (__verbose)
438         MESG("pdf_font>> ToUnicode CMap \"%s\" attached to font id=\"%s\".\n",
439              cmap_name, font->map_name);
440     }
441     pdf_release_obj(tounicode);
442   }
443 
444   return  0;
445 }
446 
447 void
pdf_close_fonts(void)448 pdf_close_fonts (void)
449 {
450   int  font_id;
451 
452   for (font_id = 0;
453        font_id < font_cache.count; font_id++) {
454     pdf_font  *font;
455 
456     font = GET_FONT(font_id);
457 
458     if (__verbose) {
459       if (font->subtype != PDF_FONT_FONTTYPE_TYPE0) {
460 	MESG("(%s", pdf_font_get_ident(font));
461 	if (__verbose > 2 &&
462 	    !pdf_font_get_flag(font, PDF_FONT_FLAG_NOEMBED)) {
463 	  MESG("[%s+%s]",
464 	       pdf_font_get_uniqueTag(font),
465 	       pdf_font_get_fontname(font));
466 	} else if (__verbose > 1) {
467 	  MESG("[%s]",
468 	       pdf_font_get_fontname(font));
469 	}
470 	if (__verbose > 1) {
471 	  if (pdf_font_get_encoding(font) >= 0) {
472 	    MESG("[%s]",
473 		 pdf_encoding_get_name(pdf_font_get_encoding(font)));
474 	  } else {
475 	    MESG("[built-in]");
476 	  }
477 	}
478 
479       }
480     }
481 
482     /* Must come before load_xxx */
483     try_load_ToUnicode_CMap(font);
484 
485     /* Type 0 is handled separately... */
486     switch (font->subtype) {
487     case PDF_FONT_FONTTYPE_TYPE1:
488       if (__verbose)
489 	MESG("[Type1]");
490       if (!pdf_font_get_flag(font, PDF_FONT_FLAG_BASEFONT))
491 	pdf_font_load_type1(font);
492       break;
493     case PDF_FONT_FONTTYPE_TYPE1C:
494       if (__verbose)
495 	MESG("[Type1C]");
496       pdf_font_load_type1c(font);
497       break;
498     case PDF_FONT_FONTTYPE_TRUETYPE:
499       if (__verbose)
500 	MESG("[TrueType]");
501       pdf_font_load_truetype(font);
502       break;
503     case PDF_FONT_FONTTYPE_TYPE3:
504       if (__verbose)
505 	MESG("[Type3/PK]");
506       pdf_font_load_pkfont (font);
507       break;
508     case PDF_FONT_FONTTYPE_TYPE0:
509       break;
510     default:
511       ERROR("Unknown font type: %d", font->subtype);
512       break;
513     }
514 
515     if (font->encoding_id >= 0 && font->subtype != PDF_FONT_FONTTYPE_TYPE0)
516       pdf_encoding_add_usedchars(font->encoding_id, font->usedchars);
517 
518     if (__verbose) {
519       if (font->subtype != PDF_FONT_FONTTYPE_TYPE0)
520 	MESG(")");
521     }
522   }
523 
524   pdf_encoding_complete();
525 
526   for (font_id = 0; font_id < font_cache.count; font_id++) {
527     pdf_font *font = GET_FONT(font_id);
528 
529     if (font->encoding_id >= 0 && font->subtype != PDF_FONT_FONTTYPE_TYPE0) {
530       pdf_obj *enc_obj = pdf_get_encoding_obj(font->encoding_id);
531       pdf_obj *tounicode;
532 
533       /* Predefined encodings (and those simplified to them) are embedded
534 	 as direct objects, but this is purely a matter of taste. */
535       if (enc_obj)
536         pdf_add_dict(font->resource,
537 		     pdf_new_name("Encoding"),
538 		     PDF_OBJ_NAMETYPE(enc_obj) ? pdf_link_obj(enc_obj) : pdf_ref_obj(enc_obj));
539 
540       if (!pdf_lookup_dict(font->resource, "ToUnicode")
541 	  && (tounicode = pdf_encoding_get_tounicode(font->encoding_id)))
542 	pdf_add_dict(font->resource,
543 		     pdf_new_name("ToUnicode"), pdf_ref_obj(tounicode));
544     } else if (font->subtype == PDF_FONT_FONTTYPE_TRUETYPE) {
545       /* encoding_id < 0 means MacRoman here (but not really)
546        * We use MacRoman as "default" encoding. */
547       pdf_add_dict(font->resource,
548                    pdf_new_name("Encoding"),
549 		   pdf_new_name("MacRomanEncoding"));
550     }
551 
552     pdf_flush_font(font);
553     pdf_clean_font_struct(font);
554   }
555   RELEASE(font_cache.fonts);
556   font_cache.fonts    = NULL;
557   font_cache.count    = 0;
558   font_cache.capacity = 0;
559 
560   Type0Font_cache_close();
561 
562   CMap_cache_close();
563   pdf_close_encodings();
564 
565   otl_close_conf();
566   agl_close_map (); /* After encoding */
567 
568   return;
569 }
570 
571 int
pdf_font_findresource(const char * tex_name,double font_scale,fontmap_rec * mrec)572 pdf_font_findresource (const char *tex_name,
573 		       double font_scale, fontmap_rec *mrec)
574 {
575   int          font_id = -1;
576   pdf_font    *font;
577   int          encoding_id = -1, cmap_id = -1;
578   const char  *fontname;
579 
580   /*
581    * Get appropriate info from map file. (PK fonts at two different
582    * point sizes would be looked up twice unecessarily.)
583    */
584   fontname = mrec ? mrec->font_name : tex_name;
585   if (mrec && mrec->enc_name) {
586 #define MAYBE_CMAP(s) (!strstr((s), ".enc") || strstr((s), ".cmap"))
587     if (MAYBE_CMAP(mrec->enc_name)) {
588       cmap_id = CMap_cache_find(mrec->enc_name);
589       if (cmap_id >= 0) {
590 	CMap  *cmap;
591 	int    cmap_type, minbytes;
592 
593 	cmap      = CMap_cache_get(cmap_id);
594 	cmap_type = CMap_get_type (cmap);
595 	minbytes  = CMap_get_profile(cmap, CMAP_PROF_TYPE_INBYTES_MIN);
596 	/*
597 	 * Check for output encoding.
598 	 */
599 	if (cmap_type != CMAP_TYPE_IDENTITY    &&
600 	    cmap_type != CMAP_TYPE_CODE_TO_CID &&
601 	    cmap_type != CMAP_TYPE_TO_UNICODE) {
602 	  WARN("Only 16-bit encoding supported for output encoding.");
603 	}
604 	/*
605 	 * Turn on map option.
606 	 */
607 	if (minbytes == 2 && mrec->opt.mapc < 0) {
608 	  if (__verbose) {
609 	    MESG("\n");
610 	    MESG("pdf_font>> Input encoding \"%s\" requires at least 2 bytes.\n",
611 		 CMap_get_name(cmap));
612 	    MESG("pdf_font>> The -m <00> option will be assumed for \"%s\".\n", mrec->font_name);
613 	  }
614 	  mrec->opt.mapc = 0; /* _FIXME_ */
615 	}
616       } else if (!strcmp(mrec->enc_name, "unicode")) {
617 	cmap_id = otf_load_Unicode_CMap(mrec->font_name,
618 					mrec->opt.index, mrec->opt.otl_tags,
619 					((mrec->opt.flags & FONTMAP_OPT_VERT) ? 1 : 0));
620 	if (cmap_id < 0) {
621 	  cmap_id = t1_load_UnicodeCMap(mrec->font_name, mrec->opt.otl_tags,
622 					((mrec->opt.flags & FONTMAP_OPT_VERT) ? 1 : 0));
623 	}
624 	if (cmap_id < 0)
625 	  ERROR("Failed to read UCS2/UCS4 TrueType cmap...");
626       }
627     }
628     if (cmap_id < 0) {
629       encoding_id = pdf_encoding_findresource(mrec->enc_name);
630       if (encoding_id < 0)
631 	ERROR("Could not find encoding file \"%s\".", mrec->enc_name);
632     }
633   }
634 
635   if (mrec && cmap_id >= 0) {
636     /*
637      * Composite Font
638      */
639     int  type0_id, found = 0;
640 
641     type0_id = Type0Font_cache_find(mrec->font_name, cmap_id, &mrec->opt);
642     if (type0_id < 0) {
643       return -1;
644     }
645 
646     for (font_id = 0;
647 	 font_id < font_cache.count; font_id++) {
648       font = GET_FONT(font_id);
649       if (font->subtype == PDF_FONT_FONTTYPE_TYPE0 &&
650 	  font->font_id == type0_id &&
651 	  font->encoding_id == cmap_id) {
652 	found = 1;
653 	if (__verbose) {
654 	  MESG("\npdf_font>> Type0 font \"%s\" (cmap_id=%d) found at font_id=%d.\n",
655 	       mrec->font_name, cmap_id, font_id);
656 	}
657 	break;
658       }
659     }
660 
661     if (!found) {
662       font_id = font_cache.count;
663       if (font_cache.count >= font_cache.capacity) {
664 	font_cache.capacity += CACHE_ALLOC_SIZE;
665 	font_cache.fonts     = RENEW(font_cache.fonts, font_cache.capacity, pdf_font);
666       }
667       font    = GET_FONT(font_id);
668       pdf_init_font_struct(font);
669 
670       font->font_id     = type0_id;
671       font->subtype     = PDF_FONT_FONTTYPE_TYPE0;
672       font->encoding_id = cmap_id;
673 
674       font_cache.count++;
675 
676       if (__verbose) {
677 	MESG("\npdf_font>> Type0 font \"%s\"", fontname);
678         MESG(" cmap_id=<%s,%d>", mrec->enc_name, font->encoding_id);
679         MESG(" opened at font_id=<%s,%d>.\n", tex_name, font_id);
680       }
681 
682     }
683   } else {
684     /*
685      * Simple Font - always embed.
686      */
687     int  found = 0;
688 
689     for (font_id = 0;
690 	 font_id < font_cache.count; font_id++) {
691       font = GET_FONT(font_id);
692       switch (font->subtype) {
693       case PDF_FONT_FONTTYPE_TYPE1:
694       case PDF_FONT_FONTTYPE_TYPE1C:
695       case PDF_FONT_FONTTYPE_TRUETYPE:
696 	/* fontname here is font file name.
697 	 * We must compare both font file name and encoding
698 	 *
699 	 * TODO: Embed a font only once if it is used
700 	 *       with two different encodings
701 	 */
702 	if (!strcmp(fontname, font->ident)   &&
703 	    encoding_id == font->encoding_id) {
704           if (mrec && mrec->opt.index == font->index)
705             found = 1;
706 	}
707 	break;
708       case PDF_FONT_FONTTYPE_TYPE3:
709 	/* There shouldn't be any encoding specified for PK font.
710 	 * It must be always font's build-in encoding.
711 	 *
712 	 * TODO: a PK font with two encodings makes no sense. Change?
713          */
714 	if (!strcmp(fontname, font->ident) &&
715 	    font_scale == font->point_size) {
716 	  found = 1;
717 	}
718 	break;
719       case PDF_FONT_FONTTYPE_TYPE0:
720 	break;
721       default:
722 	ERROR("Unknown font type: %d", font->subtype);
723 	break;
724       }
725 
726       if (found) {
727 	if (__verbose) {
728 	  MESG("\npdf_font>> Simple font \"%s\" (enc_id=%d) found at id=%d.\n",
729 	       fontname, encoding_id, font_id);
730 	}
731 	break;
732       }
733     }
734 
735 
736     if (!found) {
737       font_id = font_cache.count;
738       if (font_cache.count >= font_cache.capacity) {
739 	font_cache.capacity += CACHE_ALLOC_SIZE;
740 	font_cache.fonts     = RENEW(font_cache.fonts, font_cache.capacity, pdf_font);
741       }
742 
743       font = GET_FONT(font_id);
744 
745       pdf_init_font_struct(font);
746 
747       font->point_size  = font_scale;
748       font->encoding_id = encoding_id;
749       font->ident       = NEW(strlen(fontname) + 1, char);
750       strcpy(font->ident, fontname);
751       font->map_name    = NEW(strlen(tex_name) + 1, char);
752       strcpy(font->map_name, tex_name);
753       font->index       = (mrec && mrec->opt.index) ? mrec->opt.index : 0;
754 
755       if (pdf_font_open_type1(font) >= 0) {
756 	font->subtype = PDF_FONT_FONTTYPE_TYPE1;
757       } else if (pdf_font_open_type1c(font) >= 0) {
758 	font->subtype = PDF_FONT_FONTTYPE_TYPE1C;
759       } else if (pdf_font_open_truetype(font) >= 0) {
760 	font->subtype = PDF_FONT_FONTTYPE_TRUETYPE;
761       } else if (pdf_font_open_pkfont(font) >= 0) {
762 	font->subtype = PDF_FONT_FONTTYPE_TYPE3;
763       } else {
764 	pdf_clean_font_struct(font);
765 	return -1;
766       }
767 
768       font_cache.count++;
769 
770       if (__verbose) {
771 	MESG("\npdf_font>> Simple font \"%s\"", fontname);
772         MESG(" enc_id=<%s,%d>",
773              (mrec && mrec->enc_name) ? mrec->enc_name : "builtin", font->encoding_id);
774         MESG(" opened at font_id=<%s,%d>.\n", tex_name, font_id);
775       }
776     }
777   }
778 
779   return  font_id;
780 }
781 
782 int
pdf_font_is_in_use(pdf_font * font)783 pdf_font_is_in_use (pdf_font *font)
784 {
785   ASSERT(font);
786 
787   return ((font->reference) ? 1 : 0);
788 }
789 
790 int
pdf_font_get_index(pdf_font * font)791 pdf_font_get_index (pdf_font *font)
792 {
793   ASSERT(font);
794 
795   return font->index;
796 }
797 
798 char *
pdf_font_get_ident(pdf_font * font)799 pdf_font_get_ident (pdf_font *font)
800 {
801   ASSERT(font);
802 
803   return font->ident;
804 }
805 
806 char *
pdf_font_get_mapname(pdf_font * font)807 pdf_font_get_mapname (pdf_font *font)
808 {
809   ASSERT(font);
810 
811   return font->map_name;
812 }
813 
814 char *
pdf_font_get_fontname(pdf_font * font)815 pdf_font_get_fontname (pdf_font *font)
816 {
817   ASSERT(font);
818 
819   return font->fontname;
820 }
821 
822 pdf_obj *
pdf_font_get_resource(pdf_font * font)823 pdf_font_get_resource (pdf_font *font)
824 {
825   ASSERT(font);
826 
827   if (!font->resource) {
828     font->resource = pdf_new_dict();
829     pdf_add_dict(font->resource,
830 		 pdf_new_name("Type"),      pdf_new_name("Font"));
831     switch (font->subtype) {
832     case PDF_FONT_FONTTYPE_TYPE1:
833     case PDF_FONT_FONTTYPE_TYPE1C:
834       pdf_add_dict(font->resource,
835 		   pdf_new_name("Subtype"), pdf_new_name("Type1"));
836       break;
837     case PDF_FONT_FONTTYPE_TYPE3:
838       pdf_add_dict(font->resource,
839 		   pdf_new_name("Subtype"), pdf_new_name("Type3"));
840       break;
841     case PDF_FONT_FONTTYPE_TRUETYPE:
842       pdf_add_dict(font->resource,
843 		   pdf_new_name("Subtype"), pdf_new_name("TrueType"));
844       break;
845     default:
846       break;
847     }
848   }
849 
850   return font->resource;
851 }
852 
853 pdf_obj *
pdf_font_get_descriptor(pdf_font * font)854 pdf_font_get_descriptor (pdf_font *font)
855 {
856   ASSERT(font);
857 
858   if (!font->descriptor) {
859     font->descriptor = pdf_new_dict();
860     pdf_add_dict(font->descriptor,
861 		 pdf_new_name("Type"), pdf_new_name("FontDescriptor"));
862   }
863 
864   return font->descriptor;
865 }
866 
867 char *
pdf_font_get_usedchars(pdf_font * font)868 pdf_font_get_usedchars (pdf_font *font)
869 {
870   ASSERT(font);
871 
872   return font->usedchars;
873 }
874 
875 int
pdf_font_get_encoding(pdf_font * font)876 pdf_font_get_encoding (pdf_font *font)
877 {
878   ASSERT(font);
879 
880   return font->encoding_id;
881 }
882 
883 int
pdf_font_get_flag(pdf_font * font,int mask)884 pdf_font_get_flag (pdf_font *font, int mask)
885 {
886   ASSERT(font);
887 
888   return ((font->flags & mask) ? 1 : 0);
889 }
890 
891 #if 0
892 int
893 pdf_font_get_flags (pdf_font *font)
894 {
895   ASSERT(font);
896 
897   return font->flags;
898 }
899 #endif /* 0 */
900 
901 double
pdf_font_get_param(pdf_font * font,int param_type)902 pdf_font_get_param (pdf_font *font, int param_type)
903 {
904   double param = 0.0;
905 
906   ASSERT(font);
907 
908   switch (param_type) {
909   case PDF_FONT_PARAM_DESIGN_SIZE:
910     param = font->design_size;
911     break;
912   case PDF_FONT_PARAM_POINT_SIZE:
913     param = font->point_size;
914     break;
915   default:
916     break;
917   }
918 
919   return param;
920 }
921 
922 char *
pdf_font_get_uniqueTag(pdf_font * font)923 pdf_font_get_uniqueTag (pdf_font *font)
924 {
925   ASSERT(font);
926 
927   if (font->uniqueID[0] == '\0') {
928     pdf_font_make_uniqueTag(font->uniqueID);
929   }
930 
931   return font->uniqueID;
932 }
933 
934 int
pdf_font_set_fontname(pdf_font * font,const char * fontname)935 pdf_font_set_fontname (pdf_font *font, const char *fontname)
936 {
937   ASSERT(font && fontname);
938 
939   if (strlen(fontname) > PDF_NAME_LEN_MAX) {
940     ERROR("Unexpected error...");
941     return -1;
942   }
943   if (font->fontname) {
944     RELEASE(font->fontname);
945   }
946   font->fontname = NEW(strlen(fontname)+1, char);
947   strcpy(font->fontname, fontname);
948 
949   return 0;
950 }
951 
952 int
pdf_font_set_subtype(pdf_font * font,int subtype)953 pdf_font_set_subtype (pdf_font *font, int subtype)
954 {
955   ASSERT(font);
956 
957   font->subtype = subtype;
958 
959   return 0;
960 }
961 
962 int
pdf_font_set_flags(pdf_font * font,int flags)963 pdf_font_set_flags (pdf_font *font, int flags)
964 {
965   ASSERT(font);
966 
967   font->flags |= flags;
968 
969   return 0;
970 }
971 
972