Back to index

texmacs  1.0.7.15
pdffont.c
Go to the documentation of this file.
00001 /*  $Header: /home/cvsroot/dvipdfmx/src/pdffont.c,v 1.24 2008/11/30 21:12:27 matthias Exp $
00002 
00003     This is dvipdfmx, an eXtended version of dvipdfm by Mark A. Wicks.
00004 
00005     Copyright (C) 2008 by Jin-Hwan Cho, Matthias Franz, and Shunsaku Hirata,
00006     the dvipdfmx project team <dvipdfmx@project.ktug.or.kr>
00007     
00008     Copyright (C) 1998, 1999 by Mark A. Wicks <mwicks@kettering.edu>
00009 
00010     This program is free software; you can redistribute it and/or modify
00011     it under the terms of the GNU General Public License as published by
00012     the Free Software Foundation; either version 2 of the License, or
00013     (at your option) any later version.
00014     
00015     This program is distributed in the hope that it will be useful,
00016     but WITHOUT ANY WARRANTY; without even the implied warranty of
00017     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00018     GNU General Public License for more details.
00019     
00020     You should have received a copy of the GNU General Public License
00021     along with this program; if not, write to the Free Software
00022     Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
00023 */
00024 
00025 #if HAVE_CONFIG_H
00026 #include "config.h"
00027 #endif
00028 
00029 #include <string.h>
00030 #include <time.h>
00031 
00032 #include "system.h"
00033 #include "error.h"
00034 #include "mem.h"
00035 
00036 #include "dpxfile.h"
00037 #include "dpxutil.h"
00038 
00039 #include "pdfobj.h"
00040 
00041 #include "pdfencoding.h"
00042 #include "cmap.h"
00043 #include "unicode.h"
00044 
00045 #include "type1.h"
00046 #include "type1c.h"
00047 #include "truetype.h"
00048 
00049 #include "pkfont.h"
00050 
00051 #include "type0.h"
00052 #include "tt_cmap.h"
00053 #include "cidtype0.h"
00054 #include "otl_conf.h"
00055 
00056 #include "pdffont.h"
00057 
00058 #include "t1_load.h"
00059 
00060 static int __verbose = 0;
00061 
00062 #define MREC_HAS_TOUNICODE(m) ((m) && (m)->opt.tounicode)
00063 
00064 void
00065 pdf_font_set_verbose (void)
00066 {
00067   __verbose++;
00068   CMap_set_verbose();
00069   Type0Font_set_verbose();
00070   CIDFont_set_verbose  ();
00071   pdf_encoding_set_verbose();
00072   UC_set_verbose ();
00073   agl_set_verbose();
00074   otl_conf_set_verbose();
00075   otf_cmap_set_verbose ();
00076 }
00077 
00078 int
00079 pdf_font_get_verbose (void)
00080 {
00081   return __verbose;
00082 }
00083 
00084 void
00085 pdf_font_set_dpi (int font_dpi)
00086 {
00087   PKFont_set_dpi(font_dpi);
00088 }
00089 
00090 void
00091 pdf_font_make_uniqueTag (char *tag)
00092 {
00093   int    i;
00094   char   ch;
00095   static char first = 1;
00096 
00097   if (first) {
00098     srand(time(NULL));
00099     first = 0;
00100   }
00101 
00102   for (i = 0; i < 6; i++) {
00103     ch = rand() % 26;
00104     tag[i] = ch + 'A';
00105   }
00106   tag[6] = '\0';
00107 }
00108 
00109 
00110 struct pdf_font
00111 {
00112   char    *ident;
00113   int      subtype;
00114 
00115   char    *map_name;
00116 
00117   int      encoding_id; /* encoding or CMap */
00118 
00119   /*
00120    * If subtype is Type0, it simply points font_id
00121    * of Type0 font. Type0 and simple font is not
00122    * unified yet.
00123    */
00124   int      font_id;
00125 
00126   /* For simple font */
00127   int      index;
00128   char    *fontname;
00129   char     uniqueID[7];
00130 
00131   
00132   char *fontfile;
00133   char *tfmfile;
00134   
00135   /*
00136    * PDF font resource objects
00137    */
00138   pdf_obj *reference;
00139   pdf_obj *resource;
00140   pdf_obj *descriptor;
00141 
00142   /*
00143    * Font format specific data
00144    */
00145   char    *usedchars;
00146   int      flags;
00147 
00148   /* PK font */
00149   double   point_size;
00150   double   design_size;
00151 };
00152 
00153 static void
00154 pdf_init_font_struct (pdf_font *font)
00155 {
00156   ASSERT(font);
00157 
00158   font->ident    = NULL;
00159   font->map_name = NULL;
00160   font->subtype  = -1;
00161   font->font_id  = -1; /* Type0 ID */
00162   font->fontname = NULL;
00163   font->fontfile = NULL;
00164   font->tfmfile = NULL;
00165   memset(font->uniqueID, 0, 7);
00166   font->index    = 0;
00167 
00168   font->encoding_id = -1;
00169 
00170   font->reference   = NULL;
00171   font->resource    = NULL;
00172   font->descriptor  = NULL;
00173 
00174   font->point_size  = 0;
00175   font->design_size = 0;
00176 
00177   font->usedchars   = NULL;
00178   font->flags       = 0;
00179 
00180   return;
00181 }
00182 
00183 static void
00184 pdf_flush_font (pdf_font *font)
00185 {
00186   char *fontname, *uniqueTag;
00187 
00188   if (!font) {
00189     return;
00190   }
00191 
00192   if (font->resource && font->reference) {
00193     if (font->subtype != PDF_FONT_FONTTYPE_TYPE3) {
00194       if (pdf_font_get_flag(font, PDF_FONT_FLAG_NOEMBED)) {
00195        pdf_add_dict(font->resource,
00196                    pdf_new_name("BaseFont"), pdf_new_name(font->fontname));
00197        if (font->descriptor) {
00198          pdf_add_dict(font->descriptor,
00199                      pdf_new_name("FontName"), pdf_new_name(font->fontname));
00200        }
00201       } else {
00202        if (!font->fontname) {
00203          ERROR("Undefined in fontname... (%s)", font->ident);
00204        }
00205        fontname  = NEW(7+strlen(font->fontname)+1, char);
00206        uniqueTag = pdf_font_get_uniqueTag(font);
00207        sprintf(fontname, "%6s+%s", uniqueTag, font->fontname);
00208        pdf_add_dict(font->resource,
00209                    pdf_new_name("BaseFont"), pdf_new_name(fontname));
00210        if (font->descriptor) {
00211          pdf_add_dict(font->descriptor,
00212                      pdf_new_name("FontName"), pdf_new_name(fontname));
00213        }
00214        RELEASE(fontname);
00215       }
00216       if (font->descriptor) {
00217        pdf_add_dict(font->resource,
00218                    pdf_new_name("FontDescriptor"), pdf_ref_obj(font->descriptor));
00219       }
00220     }
00221   }
00222 
00223 
00224   if (font->resource)
00225     pdf_release_obj(font->resource);
00226   if (font->descriptor)
00227     pdf_release_obj(font->descriptor);
00228   if (font->reference)
00229     pdf_release_obj(font->reference);
00230 
00231   font->reference  = NULL;
00232   font->resource   = NULL;
00233   font->descriptor = NULL;
00234 
00235   return;
00236 }
00237 
00238 static void
00239 pdf_clean_font_struct (pdf_font *font)
00240 {
00241   if (font) {
00242     if (font->ident)
00243       RELEASE(font->ident);
00244     if (font->map_name)
00245       RELEASE(font->map_name);
00246     if (font->fontname)
00247       RELEASE(font->fontname);
00248     if (font->fontfile)
00249       RELEASE(font->fontfile);
00250     if (font->tfmfile)
00251       RELEASE(font->tfmfile);
00252     if (font->usedchars)
00253       RELEASE(font->usedchars);
00254 
00255     if (font->reference)
00256       ERROR("pdf_font>> Object not flushed.");
00257     if (font->resource)
00258       ERROR("pdf_font> Object not flushed.");
00259     if (font->descriptor)
00260       ERROR("pdf_font>> Object not flushed.");
00261 
00262     font->ident     = NULL;
00263     font->map_name  = NULL;
00264     font->fontname  = NULL;
00265     font->fontfile  = NULL;
00266     font->tfmfile  = NULL;
00267     font->usedchars = NULL;
00268   }
00269 
00270   return;
00271 }
00272 
00273 #define CACHE_ALLOC_SIZE 16u
00274 
00275 static struct {
00276   int       count;
00277   int       capacity;
00278   pdf_font *fonts;
00279 } font_cache = {
00280   0, 0, NULL
00281 };
00282 
00283 void
00284 pdf_init_fonts (void)
00285 {
00286   ASSERT(font_cache.fonts == NULL);  
00287 
00288   agl_init_map();
00289   otl_init_conf();
00290 
00291   CMap_cache_init();
00292   pdf_init_encodings();
00293 
00294   Type0Font_cache_init();
00295 
00296   font_cache.count    = 0;
00297   font_cache.capacity = CACHE_ALLOC_SIZE;
00298   font_cache.fonts    = NEW(font_cache.capacity, pdf_font);
00299 }
00300 
00301 #define CHECK_ID(n) do {\
00302   if ((n) < 0 || (n) >= font_cache.count) {\
00303     ERROR("Invalid font ID: %d", (n));\
00304   }\
00305 } while (0)
00306 #define GET_FONT(n)  (&(font_cache.fonts[(n)]))
00307 
00308 
00309 pdf_obj *
00310 pdf_get_font_reference (int font_id)
00311 {
00312   pdf_font  *font;
00313 
00314   CHECK_ID(font_id);
00315 
00316   font = GET_FONT(font_id);
00317   if (font->subtype == PDF_FONT_FONTTYPE_TYPE0) {
00318     Type0Font *t0font;
00319 
00320     t0font = Type0Font_cache_get(font->font_id);
00321     return Type0Font_get_resource(t0font);
00322   } else {
00323     if (!font->reference) {
00324       font->reference = pdf_ref_obj(pdf_font_get_resource(font));
00325     }
00326   }
00327 
00328   return pdf_link_obj(font->reference);
00329 }
00330 
00331 char *
00332 pdf_get_font_usedchars (int font_id)
00333 {
00334   pdf_font *font;
00335 
00336   CHECK_ID(font_id);
00337 
00338   font = GET_FONT(font_id);
00339   if (font->subtype == PDF_FONT_FONTTYPE_TYPE0) {
00340     Type0Font *t0font;
00341 
00342     t0font = Type0Font_cache_get(font->font_id);
00343     return Type0Font_get_usedchars(t0font);
00344   } else {
00345     if (!font->usedchars) {
00346       font->usedchars = NEW(256, char);
00347       memset(font->usedchars, 0, 256 * sizeof(char));
00348     }
00349     return font->usedchars;
00350   }
00351 }
00352 
00353 int
00354 pdf_get_font_wmode (int font_id)
00355 {
00356   pdf_font *font;
00357 
00358   CHECK_ID(font_id);
00359 
00360   font = GET_FONT(font_id);
00361   if (font->subtype == PDF_FONT_FONTTYPE_TYPE0) {
00362     Type0Font *t0font;
00363 
00364     t0font = Type0Font_cache_get(font->font_id);
00365     return Type0Font_get_wmode(t0font);
00366   } else {
00367     return 0;
00368   }
00369 }
00370 
00371 int
00372 pdf_get_font_subtype (int font_id)
00373 {
00374   pdf_font *font;
00375 
00376   CHECK_ID(font_id);
00377 
00378   font = GET_FONT(font_id);
00379 
00380   return font->subtype;
00381 }
00382 
00383 #if 0
00384 char *
00385 pdf_get_font_fontname (int font_id)
00386 {
00387   pdf_font *font;
00388 
00389   CHECK_ID(font_id);
00390 
00391   font = GET_FONT(font_id);
00392 
00393   return font->fontname;
00394 }
00395 #endif
00396 
00397 
00398 int
00399 pdf_get_font_encoding (int font_id)
00400 {
00401   pdf_font *font;
00402 
00403   CHECK_ID(font_id);
00404 
00405   font = GET_FONT(font_id);
00406 
00407   return font->encoding_id;
00408 }
00409 
00410 /* The rule for ToUnicode creation is:
00411  *
00412  *  If "tounicode" option is specified in fontmap, use that.
00413  *  If there is ToUnicode CMap with same name as TFM, use that.
00414  *  If no "tounicode" option is used and no ToUnicode CMap with
00415  *  same name as TFM is found, create ToUnicode CMap from glyph
00416  *  names and AGL file.
00417  */
00418 static int
00419 try_load_ToUnicode_CMap (pdf_font *font)
00420 {
00421   pdf_obj     *fontdict;
00422   pdf_obj     *tounicode;
00423   const char  *cmap_name = NULL;
00424   fontmap_rec *mrec; /* Be sure fontmap is still alive here */
00425 
00426   ASSERT(font);
00427 
00428   /* We are using different encoding for Type0 font.
00429    * This feature is unavailable for them.
00430    */
00431   if (font->subtype == PDF_FONT_FONTTYPE_TYPE0)
00432     return  0;
00433 
00434   ASSERT(font->map_name);
00435 
00436   mrec = pdf_lookup_fontmap_record(font->map_name);
00437   if (MREC_HAS_TOUNICODE(mrec))
00438     cmap_name = mrec->opt.tounicode;
00439   else {
00440     cmap_name = font->map_name;
00441   }
00442 
00443   fontdict  = pdf_font_get_resource(font);
00444   tounicode = pdf_load_ToUnicode_stream(cmap_name);
00445   if (!tounicode && MREC_HAS_TOUNICODE(mrec))
00446     WARN("Failed to read ToUnicode mapping \"%s\"...", mrec->opt.tounicode);
00447   else if (tounicode) {
00448     if (pdf_obj_typeof(tounicode) != PDF_STREAM)
00449       ERROR("Object returned by pdf_load_ToUnicode_stream() not stream object! (This must be bug)");
00450     else if (pdf_stream_length(tounicode) > 0) {
00451       pdf_add_dict(fontdict,
00452                    pdf_new_name("ToUnicode"),
00453                    pdf_ref_obj (tounicode)); /* _FIXME_ */
00454       if (__verbose)
00455         MESG("pdf_font>> ToUnicode CMap \"%s\" attached to font id=\"%s\".\n",
00456              cmap_name, font->map_name);
00457     }
00458     pdf_release_obj(tounicode);
00459   }
00460 
00461   return  0;
00462 }
00463 
00464 void
00465 pdf_close_fonts (void)
00466 {
00467   int  font_id, retval;
00468 
00469   for (font_id = 0;
00470        font_id < font_cache.count; font_id++) {
00471     pdf_font  *font;
00472 
00473     font = GET_FONT(font_id);
00474 
00475     if (__verbose) {
00476       if (font->subtype != PDF_FONT_FONTTYPE_TYPE0) {
00477        MESG("(%s", pdf_font_get_ident(font));
00478        if (__verbose > 2 &&
00479            !pdf_font_get_flag(font, PDF_FONT_FLAG_NOEMBED)) {
00480          MESG("[%s+%s]",
00481               pdf_font_get_uniqueTag(font),
00482               pdf_font_get_fontname(font));
00483        } else if (__verbose > 1) {
00484          MESG("[%s]",
00485               pdf_font_get_fontname(font));
00486        }
00487        if (__verbose > 1) {
00488          if (pdf_font_get_encoding(font) >= 0) {
00489            MESG("[%s]",
00490                pdf_encoding_get_name(pdf_font_get_encoding(font)));
00491          } else {
00492            MESG("[built-in]");
00493          }
00494        }
00495 
00496       }
00497     }
00498 
00499     /* Must come before load_xxx */
00500     try_load_ToUnicode_CMap(font);
00501 
00502     /* Type 0 is handled separately... */
00503     switch (font->subtype) {
00504     case PDF_FONT_FONTTYPE_TYPE1:
00505       if (__verbose)
00506        MESG("[Type1]");
00507       if (!pdf_font_get_flag(font, PDF_FONT_FLAG_BASEFONT))
00508        retval = pdf_font_load_type1(font);
00509       else
00510        retval = 0;
00511       break;
00512     case PDF_FONT_FONTTYPE_TYPE1C:
00513       if (__verbose)
00514        MESG("[Type1C]");
00515       retval = pdf_font_load_type1c(font);
00516       break;
00517     case PDF_FONT_FONTTYPE_TRUETYPE:
00518       if (__verbose)
00519        MESG("[TrueType]");
00520       retval = pdf_font_load_truetype(font);
00521       break;
00522     case PDF_FONT_FONTTYPE_TYPE3:
00523       if (__verbose)
00524        MESG("[Type3/PK]");
00525       retval = pdf_font_load_pkfont (font);
00526       break;
00527     case PDF_FONT_FONTTYPE_TYPE0:
00528       break;
00529     default:
00530       ERROR("Unknown font type: %d", font->subtype);
00531       break;
00532     }
00533 
00534     if (font->encoding_id >= 0 && font->subtype != PDF_FONT_FONTTYPE_TYPE0)
00535       pdf_encoding_add_usedchars(font->encoding_id, font->usedchars);
00536 
00537     if (__verbose) {
00538       if (font->subtype != PDF_FONT_FONTTYPE_TYPE0)
00539        MESG(")");
00540     }
00541   }
00542 
00543   pdf_encoding_complete();
00544 
00545   for (font_id = 0; font_id < font_cache.count; font_id++) {
00546     pdf_font *font = GET_FONT(font_id);
00547 
00548     if (font->encoding_id >= 0 && font->subtype != PDF_FONT_FONTTYPE_TYPE0) {
00549       pdf_obj *enc_obj = pdf_get_encoding_obj(font->encoding_id);
00550       pdf_obj *tounicode;
00551 
00552       /* Predefined encodings (and those simplified to them) are embedded
00553         as direct objects, but this is purely a matter of taste. */
00554       if (enc_obj)
00555         pdf_add_dict(font->resource,
00556                    pdf_new_name("Encoding"),
00557                    PDF_OBJ_NAMETYPE(enc_obj) ? pdf_link_obj(enc_obj) : pdf_ref_obj(enc_obj));
00558 
00559       if (!pdf_lookup_dict(font->resource, "ToUnicode")
00560          && (tounicode = pdf_encoding_get_tounicode(font->encoding_id)))
00561        pdf_add_dict(font->resource,
00562                    pdf_new_name("ToUnicode"), pdf_ref_obj(tounicode));
00563     } else if (font->subtype == PDF_FONT_FONTTYPE_TRUETYPE) {
00564       /* encoding_id < 0 means MacRoman here (but not really)
00565        * We use MacRoman as "default" encoding. */
00566       pdf_add_dict(font->resource,
00567                    pdf_new_name("Encoding"),
00568                  pdf_new_name("MacRomanEncoding"));
00569     }
00570 
00571     pdf_flush_font(font);
00572     pdf_clean_font_struct(font);
00573   }
00574   RELEASE(font_cache.fonts);
00575   font_cache.fonts    = NULL;
00576   font_cache.count    = 0;
00577   font_cache.capacity = 0;
00578 
00579   Type0Font_cache_close();
00580 
00581   CMap_cache_close();
00582   pdf_close_encodings();
00583 
00584   otl_close_conf();
00585   agl_close_map (); /* After encoding */
00586 
00587   return;
00588 }
00589 
00590 int
00591 pdf_font_findresource (const char *tex_name,
00592                      double font_scale, fontmap_rec *mrec)
00593 {
00594   int          font_id = -1;
00595   pdf_font    *font;
00596   int          encoding_id = -1, cmap_id = -1;
00597   const char  *fontname;
00598 
00599   /*
00600    * Get appropriate info from map file. (PK fonts at two different
00601    * point sizes would be looked up twice unecessarily.)
00602    */
00603   fontname = mrec ? mrec->font_name : tex_name;
00604   if (mrec && mrec->enc_name) {
00605 #define MAYBE_CMAP(s) (!strstr((s), ".enc") || strstr((s), ".cmap"))
00606     if (MAYBE_CMAP(mrec->enc_name)) {
00607       cmap_id = CMap_cache_find(mrec->enc_name);
00608       if (cmap_id >= 0) {
00609        CMap  *cmap;
00610        int    cmap_type, minbytes;
00611 
00612        cmap      = CMap_cache_get(cmap_id);
00613        cmap_type = CMap_get_type (cmap);
00614        minbytes  = CMap_get_profile(cmap, CMAP_PROF_TYPE_INBYTES_MIN);
00615        /*
00616         * Check for output encoding.
00617         */
00618        if (cmap_type != CMAP_TYPE_IDENTITY    &&
00619            cmap_type != CMAP_TYPE_CODE_TO_CID &&
00620            cmap_type != CMAP_TYPE_TO_UNICODE) {
00621          WARN("Only 16-bit encoding supported for output encoding.");
00622        }
00623        /*
00624         * Turn on map option.
00625         */
00626        if (minbytes == 2 && mrec->opt.mapc < 0) {
00627          if (__verbose) {
00628            MESG("\n");
00629            MESG("pdf_font>> Input encoding \"%s\" requires at least 2 bytes.\n",
00630                CMap_get_name(cmap));
00631            MESG("pdf_font>> The -m <00> option will be assumed for \"%s\".\n", mrec->font_name);
00632          }
00633          mrec->opt.mapc = 0; /* _FIXME_ */
00634        }
00635       } else if (!strcmp(mrec->enc_name, "unicode")) {
00636        cmap_id = otf_load_Unicode_CMap(mrec->font_name,
00637                                    mrec->opt.index, mrec->opt.otl_tags,
00638                                    ((mrec->opt.flags & FONTMAP_OPT_VERT) ? 1 : 0));
00639        if (cmap_id < 0) {
00640          cmap_id = t1_load_UnicodeCMap(mrec->font_name, mrec->opt.otl_tags,
00641                                    ((mrec->opt.flags & FONTMAP_OPT_VERT) ? 1 : 0));
00642        }
00643        if (cmap_id < 0)
00644          ERROR("Failed to read UCS2/UCS4 TrueType cmap...");
00645       }
00646     }
00647     if (cmap_id < 0) {
00648       encoding_id = pdf_encoding_findresource(mrec->enc_name);
00649       if (encoding_id < 0)
00650        ERROR("Could not find encoding file \"%s\".", mrec->enc_name);
00651     }
00652   }
00653 
00654   if (mrec && cmap_id >= 0) {
00655     /*
00656      * Composite Font
00657      */
00658     int  type0_id, found = 0;
00659 
00660     type0_id = pdf_font_findfont0(mrec->font_name, cmap_id, &mrec->opt);
00661     if (type0_id < 0) {
00662       return -1;
00663     }
00664 
00665     for (font_id = 0;
00666         font_id < font_cache.count; font_id++) {
00667       font = GET_FONT(font_id);
00668       if (font->subtype == PDF_FONT_FONTTYPE_TYPE0 &&
00669          font->font_id == type0_id &&
00670          font->encoding_id == cmap_id) {
00671        found = 1;
00672        if (__verbose) {
00673          MESG("\npdf_font>> Type0 font \"%s\" (cmap_id=%d) found at font_id=%d.\n",
00674               mrec->font_name, cmap_id, font_id);
00675        }
00676        break;
00677       }
00678     }
00679 
00680     if (!found) {
00681       font_id = font_cache.count;
00682       if (font_cache.count >= font_cache.capacity) {
00683        font_cache.capacity += CACHE_ALLOC_SIZE;
00684        font_cache.fonts     = RENEW(font_cache.fonts, font_cache.capacity, pdf_font);
00685       }
00686       font    = GET_FONT(font_id);
00687       pdf_init_font_struct(font);
00688 
00689       font->font_id     = type0_id;
00690       font->subtype     = PDF_FONT_FONTTYPE_TYPE0;
00691       font->encoding_id = cmap_id;
00692 
00693       font_cache.count++;
00694 
00695       if (__verbose) {
00696        MESG("\npdf_font>> Type0 font \"%s\"", fontname);
00697         MESG(" cmap_id=<%s,%d>", mrec->enc_name, font->encoding_id);
00698         MESG(" opened at font_id=<%s,%d>.\n", tex_name, font_id);
00699       }
00700 
00701     }
00702   } else {
00703     /*
00704      * Simple Font - always embed.
00705      */
00706     int  found = 0;
00707 
00708     for (font_id = 0;
00709         font_id < font_cache.count; font_id++) {
00710       font = GET_FONT(font_id);
00711       switch (font->subtype) {
00712       case PDF_FONT_FONTTYPE_TYPE1:
00713       case PDF_FONT_FONTTYPE_TYPE1C:
00714       case PDF_FONT_FONTTYPE_TRUETYPE:
00715        /* fontname here is font file name.
00716         * We must compare both font file name and encoding
00717         *
00718         * TODO: Embed a font only once if it is used
00719         *       with two different encodings
00720         */
00721        if (!strcmp(fontname, font->ident)   &&
00722            encoding_id == font->encoding_id) {
00723           if (mrec && mrec->opt.index == font->index)
00724             found = 1;
00725        }
00726        break;
00727       case PDF_FONT_FONTTYPE_TYPE3:
00728        /* There shouldn't be any encoding specified for PK font.
00729         * It must be always font's build-in encoding.
00730         *
00731         * TODO: a PK font with two encodings makes no sense. Change?
00732          */
00733        if (!strcmp(fontname, font->ident) &&
00734            font_scale == font->point_size) {
00735          found = 1;
00736        }
00737        break;
00738       case PDF_FONT_FONTTYPE_TYPE0:
00739        break;
00740       default:
00741        ERROR("Unknown font type: %d", font->subtype);
00742        break;
00743       }
00744 
00745       if (found) {
00746        if (__verbose) {
00747          MESG("\npdf_font>> Simple font \"%s\" (enc_id=%d) found at id=%d.\n",
00748               fontname, encoding_id, font_id);
00749        }
00750        break;
00751       }
00752     }
00753 
00754 
00755     if (!found) {
00756       font_id = font_cache.count;
00757       if (font_cache.count >= font_cache.capacity) {
00758        font_cache.capacity += CACHE_ALLOC_SIZE;
00759        font_cache.fonts     = RENEW(font_cache.fonts, font_cache.capacity, pdf_font);
00760       }
00761 
00762       font = GET_FONT(font_id);
00763 
00764       pdf_init_font_struct(font);
00765 
00766       font->point_size  = font_scale;
00767       font->encoding_id = encoding_id;
00768       font->ident       = NEW(strlen(fontname) + 1, char);
00769       strcpy(font->ident, fontname);
00770       font->map_name    = NEW(strlen(tex_name) + 1, char);
00771       strcpy(font->map_name, tex_name);
00772       font->index       = (mrec && mrec->opt.index) ? mrec->opt.index : 0;
00773 
00774       if (pdf_font_open_type1(font) >= 0) {
00775        font->subtype = PDF_FONT_FONTTYPE_TYPE1;
00776       } else if (pdf_font_open_type1c(font) >= 0) {
00777        font->subtype = PDF_FONT_FONTTYPE_TYPE1C;
00778       } else if (pdf_font_open_truetype(font) >= 0) {
00779        font->subtype = PDF_FONT_FONTTYPE_TRUETYPE;
00780       } else if (pdf_font_open_pkfont(font) >= 0) {
00781        font->subtype = PDF_FONT_FONTTYPE_TYPE3;
00782       } else {
00783        pdf_clean_font_struct(font);
00784        return -1;
00785       }
00786 
00787       font_cache.count++;
00788 
00789       if (__verbose) {
00790        MESG("\npdf_font>> Simple font \"%s\"", fontname);
00791         MESG(" enc_id=<%s,%d>",
00792              (mrec && mrec->enc_name) ? mrec->enc_name : "builtin", font->encoding_id);
00793         MESG(" opened at font_id=<%s,%d>.\n", tex_name, font_id);
00794       }
00795     }
00796   }
00797 
00798   return  font_id;
00799 }
00800 
00801 
00802 
00803 
00804 int
00805 pdf_font_physical (const char *tex_name,
00806                        double font_scale, const char *font_file, const char *tfm_file)
00807 {
00808   int          font_id = -1;
00809   pdf_font    *font;
00810   int          encoding_id = -1, cmap_id = -1;
00811   const char  *fontname;
00812   
00813   
00814   fontmap_rec *mrec = NULL; // FIXME: maybe reenable mrec in future
00815   
00816   /*
00817    * Get appropriate info from map file. (PK fonts at two different
00818    * point sizes would be looked up twice unecessarily.)
00819    */
00820   fontname = mrec ? mrec->font_name : tex_name;
00821   if (mrec && mrec->enc_name) {
00822 #define MAYBE_CMAP(s) (!strstr((s), ".enc") || strstr((s), ".cmap"))
00823     if (MAYBE_CMAP(mrec->enc_name)) {
00824       cmap_id = CMap_cache_find(mrec->enc_name);
00825       if (cmap_id >= 0) {
00826         CMap  *cmap;
00827         int    cmap_type, minbytes;
00828         
00829         cmap      = CMap_cache_get(cmap_id);
00830         cmap_type = CMap_get_type (cmap);
00831         minbytes  = CMap_get_profile(cmap, CMAP_PROF_TYPE_INBYTES_MIN);
00832         /*
00833          * Check for output encoding.
00834          */
00835         if (cmap_type != CMAP_TYPE_IDENTITY    &&
00836             cmap_type != CMAP_TYPE_CODE_TO_CID &&
00837             cmap_type != CMAP_TYPE_TO_UNICODE) {
00838           WARN("Only 16-bit encoding supported for output encoding.");
00839         }
00840         /*
00841          * Turn on map option.
00842          */
00843         if (minbytes == 2 && mrec->opt.mapc < 0) {
00844           if (__verbose) {
00845             MESG("\n");
00846             MESG("pdf_font>> Input encoding \"%s\" requires at least 2 bytes.\n",
00847                  CMap_get_name(cmap));
00848             MESG("pdf_font>> The -m <00> option will be assumed for \"%s\".\n", mrec->font_name);
00849           }
00850           mrec->opt.mapc = 0; /* _FIXME_ */
00851         }
00852       } else if (!strcmp(mrec->enc_name, "unicode")) {
00853         cmap_id = otf_load_Unicode_CMap(mrec->font_name,
00854                                         mrec->opt.index, mrec->opt.otl_tags,
00855                                         ((mrec->opt.flags & FONTMAP_OPT_VERT) ? 1 : 0));
00856         if (cmap_id < 0) {
00857           cmap_id = t1_load_UnicodeCMap(mrec->font_name, mrec->opt.otl_tags,
00858                                         ((mrec->opt.flags & FONTMAP_OPT_VERT) ? 1 : 0));
00859         }
00860         if (cmap_id < 0)
00861           ERROR("Failed to read UCS2/UCS4 TrueType cmap...");
00862       }
00863     }
00864     if (cmap_id < 0) {
00865       encoding_id = pdf_encoding_findresource(mrec->enc_name);
00866       if (encoding_id < 0)
00867         ERROR("Could not find encoding file \"%s\".", mrec->enc_name);
00868     }
00869   }
00870   
00871   if (mrec && cmap_id >= 0) {
00872     /*
00873      * Composite Font
00874      */
00875     int  type0_id, found = 0;
00876     
00877     type0_id = pdf_font_findfont0(mrec->font_name, cmap_id, &mrec->opt);
00878     if (type0_id < 0) {
00879       return -1;
00880     }
00881     
00882     for (font_id = 0;
00883          font_id < font_cache.count; font_id++) {
00884       font = GET_FONT(font_id);
00885       if (font->subtype == PDF_FONT_FONTTYPE_TYPE0 &&
00886           font->font_id == type0_id &&
00887           font->encoding_id == cmap_id) {
00888         found = 1;
00889         if (__verbose) {
00890           MESG("\npdf_font>> Type0 font \"%s\" (cmap_id=%d) found at font_id=%d.\n",
00891                mrec->font_name, cmap_id, font_id);
00892         }
00893         break;
00894       }
00895     }
00896     
00897     if (!found) {
00898       font_id = font_cache.count;
00899       if (font_cache.count >= font_cache.capacity) {
00900         font_cache.capacity += CACHE_ALLOC_SIZE;
00901         font_cache.fonts     = RENEW(font_cache.fonts, font_cache.capacity, pdf_font);
00902       }
00903       font    = GET_FONT(font_id);
00904       pdf_init_font_struct(font);
00905       
00906       font->font_id     = type0_id;
00907       font->subtype     = PDF_FONT_FONTTYPE_TYPE0;
00908       font->encoding_id = cmap_id;
00909       
00910       font_cache.count++;
00911       
00912       if (__verbose) {
00913         MESG("\npdf_font>> Type0 font \"%s\"", fontname);
00914         MESG(" cmap_id=<%s,%d>", mrec->enc_name, font->encoding_id);
00915         MESG(" opened at font_id=<%s,%d>.\n", tex_name, font_id);
00916       }
00917       
00918     }
00919   } else {
00920     /*
00921      * Simple Font - always embed.
00922      */
00923     int  found = 0;
00924     
00925     for (font_id = 0;
00926          font_id < font_cache.count; font_id++) {
00927       font = GET_FONT(font_id);
00928       switch (font->subtype) {
00929         case PDF_FONT_FONTTYPE_TYPE1:
00930         case PDF_FONT_FONTTYPE_TYPE1C:
00931         case PDF_FONT_FONTTYPE_TRUETYPE:
00932           /* fontname here is font file name.
00933            * We must compare both font file name and encoding
00934            *
00935            * TODO: Embed a font only once if it is used
00936            *       with two different encodings
00937            */
00938           if (!strcmp(fontname, font->ident)   &&
00939               encoding_id == font->encoding_id) {
00940             if (mrec && mrec->opt.index == font->index)
00941               found = 1;
00942           }
00943           break;
00944         case PDF_FONT_FONTTYPE_TYPE3:
00945           /* There shouldn't be any encoding specified for PK font.
00946            * It must be always font's build-in encoding.
00947            *
00948            * TODO: a PK font with two encodings makes no sense. Change?
00949            */
00950           if (!strcmp(fontname, font->ident) &&
00951               font_scale == font->point_size) {
00952             found = 1;
00953           }
00954           break;
00955         case PDF_FONT_FONTTYPE_TYPE0:
00956           break;
00957         default:
00958           ERROR("Unknown font type: %d", font->subtype);
00959           break;
00960       }
00961       
00962       if (found) {
00963         if (__verbose) {
00964           MESG("\npdf_font>> Simple font \"%s\" (enc_id=%d) found at id=%d.\n",
00965                fontname, encoding_id, font_id);
00966         }
00967         break;
00968       }
00969     }
00970     
00971     
00972     if (!found) {
00973       font_id = font_cache.count;
00974       if (font_cache.count >= font_cache.capacity) {
00975         font_cache.capacity += CACHE_ALLOC_SIZE;
00976         font_cache.fonts     = RENEW(font_cache.fonts, font_cache.capacity, pdf_font);
00977       }
00978       
00979       font = GET_FONT(font_id);
00980       
00981       pdf_init_font_struct(font);
00982       
00983       font->point_size  = font_scale;
00984       font->encoding_id = encoding_id;
00985       font->ident       = NEW(strlen(fontname) + 1, char);
00986       strcpy(font->ident, fontname);
00987       font->map_name    = NEW(strlen(tex_name) + 1, char);
00988       strcpy(font->map_name, tex_name);
00989       font->index       = (mrec && mrec->opt.index) ? mrec->opt.index : 0;
00990       if (font_file) {  
00991         font->fontfile       = NEW(strlen(font_file) + 1, char);
00992         strcpy(font->fontfile, font_file);
00993       }
00994       if (tfm_file) {
00995         font->tfmfile       = NEW(strlen(tfm_file) + 1, char);
00996         strcpy(font->tfmfile, tfm_file);
00997       }
00998       if (pdf_font_open_type1(font) >= 0) {
00999         font->subtype = PDF_FONT_FONTTYPE_TYPE1;
01000       } else if (pdf_font_open_type1c(font) >= 0) {
01001         font->subtype = PDF_FONT_FONTTYPE_TYPE1C;
01002       } else if (pdf_font_open_truetype(font) >= 0) {
01003         font->subtype = PDF_FONT_FONTTYPE_TRUETYPE;
01004       } else if (pdf_font_open_pkfont(font) >= 0) {
01005         font->subtype = PDF_FONT_FONTTYPE_TYPE3;
01006       } else {
01007         pdf_clean_font_struct(font);
01008         return -1;
01009       }
01010       
01011       font_cache.count++;
01012       
01013       if (__verbose) {
01014         MESG("\npdf_font>> Simple font \"%s\"", fontname);
01015         MESG(" enc_id=<%s,%d>",
01016              (mrec && mrec->enc_name) ? mrec->enc_name : "builtin", font->encoding_id);
01017         MESG(" opened at font_id=<%s,%d>.\n", tex_name, font_id);
01018       }
01019     }
01020   }
01021   
01022   return  font_id;
01023 }
01024 
01025 
01026 int
01027 pdf_font_physical_old (const char *tex_name,
01028                        double font_scale, const char *font_file)
01029 {
01030   int          font_id = -1;
01031   pdf_font    *font;
01032   int          encoding_id = -1;
01033   const char  *fontname;
01034   
01035   /*
01036    * Get appropriate info from map file. (PK fonts at two different
01037    * point sizes would be looked up twice unecessarily.)
01038    */
01039   fontname = tex_name;
01040   {
01041     /*
01042      * Simple Font - always embed.
01043      */
01044     int  found = 0;
01045     
01046     for (font_id = 0;
01047          font_id < font_cache.count; font_id++) {
01048       font = GET_FONT(font_id);
01049       switch (font->subtype) {
01050         case PDF_FONT_FONTTYPE_TYPE1:
01051         case PDF_FONT_FONTTYPE_TYPE1C:
01052         case PDF_FONT_FONTTYPE_TRUETYPE:
01053           /* fontname here is font file name.
01054            * We must compare both font file name and encoding
01055            *
01056            * TODO: Embed a font only once if it is used
01057            *       with two different encodings
01058            */
01059           if (!strcmp(fontname, font->ident)   &&
01060               encoding_id == font->encoding_id) {
01061               found = 1;
01062           }
01063           break;
01064         case PDF_FONT_FONTTYPE_TYPE3:
01065           /* There shouldn't be any encoding specified for PK font.
01066            * It must be always font's build-in encoding.
01067            *
01068            * TODO: a PK font with two encodings makes no sense. Change?
01069            */
01070           if (!strcmp(fontname, font->ident) &&
01071               font_scale == font->point_size) {
01072             found = 1;
01073           }
01074           break;
01075         case PDF_FONT_FONTTYPE_TYPE0:
01076           break;
01077         default:
01078           ERROR("Unknown font type: %d", font->subtype);
01079           break;
01080       }
01081       
01082       if (found) {
01083         if (__verbose) {
01084           MESG("\npdf_font>> Simple font \"%s\" (enc_id=%d) found at id=%d.\n",
01085                fontname, encoding_id, font_id);
01086         }
01087         break;
01088       }
01089     }
01090     
01091     
01092     if (!found) {
01093       font_id = font_cache.count;
01094       if (font_cache.count >= font_cache.capacity) {
01095         font_cache.capacity += CACHE_ALLOC_SIZE;
01096         font_cache.fonts     = RENEW(font_cache.fonts, font_cache.capacity, pdf_font);
01097       }
01098       
01099       font = GET_FONT(font_id);
01100       
01101       pdf_init_font_struct(font);
01102       
01103       font->point_size  = font_scale;
01104       font->encoding_id = encoding_id;
01105       font->ident       = NEW(strlen(fontname) + 1, char);
01106       strcpy(font->ident, fontname);
01107       font->map_name    = NEW(strlen(tex_name) + 1, char);
01108       strcpy(font->map_name, tex_name);
01109       font->index       = 0;
01110       
01111       font->subtype = PDF_FONT_FONTTYPE_TYPE1;
01112 
01113       font->fontfile       = NEW(strlen(font_file) + 1, char);
01114       strcpy(font->fontfile, font_file);
01115       
01116       {
01117         char    *ident;
01118         FILE    *fp;
01119         char     fontname[PDF_NAME_LEN_MAX+1];
01120 
01121         memset(fontname, 0, PDF_NAME_LEN_MAX+1);
01122         
01123         fp = MFOPEN(font_file, FOPEN_RBIN_MODE);
01124 
01125         if (!fp || !is_pfb(fp) || t1_get_fontname(fp, fontname) < 0) {
01126           ERROR("Failed to read Type 1 font \"%s\".", font_file);
01127           pdf_clean_font_struct(font);
01128           return -1;
01129         }
01130         
01131         MFCLOSE(fp);
01132           
01133         pdf_font_set_fontname(font, fontname);
01134       }
01135       
01136       font_cache.count++;
01137       
01138       if (__verbose) {
01139         MESG("\npdf_font>> Simple font \"%s\"", fontname);
01140         MESG(" enc_id=<%s,%d>",
01141               "builtin", font->encoding_id);
01142         MESG(" opened at font_id=<%s,%d>.\n", tex_name, font_id);
01143       }
01144     }
01145   }
01146   
01147   return  font_id;
01148 
01149 }
01150 
01151 
01152 
01153 int 
01154 pdf_font_is_in_use (pdf_font *font)
01155 {
01156   ASSERT(font);
01157 
01158   return ((font->reference) ? 1 : 0);
01159 }
01160 
01161 int
01162 pdf_font_get_index (pdf_font *font)
01163 {
01164   ASSERT(font);
01165 
01166   return font->index;
01167 }
01168 
01169 char *
01170 pdf_font_get_ident (pdf_font *font)
01171 {
01172   ASSERT(font);
01173 
01174   return font->ident;
01175 }
01176 
01177 char *
01178 pdf_font_get_mapname (pdf_font *font)
01179 {
01180   ASSERT(font);
01181 
01182   return font->map_name;
01183 }
01184 
01185 char *
01186 pdf_font_get_fontname (pdf_font *font)
01187 {
01188   ASSERT(font);
01189 
01190   return font->fontname;
01191 }
01192 
01193 
01194 char *
01195 pdf_font_get_fontfile (pdf_font *font)
01196 {
01197   ASSERT(font);
01198   
01199   return font->fontfile;
01200 }
01201 
01202 char *
01203 pdf_font_get_tfmfile (pdf_font *font)
01204 {
01205   ASSERT(font);
01206   
01207   return font->tfmfile;
01208 }
01209 
01210 pdf_obj *
01211 pdf_font_get_resource (pdf_font *font)
01212 {
01213   ASSERT(font);
01214 
01215   if (!font->resource) {
01216     font->resource = pdf_new_dict();
01217     pdf_add_dict(font->resource,
01218                pdf_new_name("Type"),      pdf_new_name("Font"));
01219     switch (font->subtype) {
01220     case PDF_FONT_FONTTYPE_TYPE1:
01221     case PDF_FONT_FONTTYPE_TYPE1C:
01222       pdf_add_dict(font->resource,
01223                  pdf_new_name("Subtype"), pdf_new_name("Type1"));
01224       break;
01225     case PDF_FONT_FONTTYPE_TYPE3:
01226       pdf_add_dict(font->resource,
01227                  pdf_new_name("Subtype"), pdf_new_name("Type3"));
01228       break;
01229     case PDF_FONT_FONTTYPE_TRUETYPE:
01230       pdf_add_dict(font->resource,
01231                  pdf_new_name("Subtype"), pdf_new_name("TrueType"));
01232       break;
01233     default:
01234       break;
01235     }
01236   }
01237 
01238   return font->resource;
01239 }
01240 
01241 pdf_obj *
01242 pdf_font_get_descriptor (pdf_font *font)
01243 {
01244   ASSERT(font);
01245 
01246   if (!font->descriptor) {
01247     font->descriptor = pdf_new_dict();
01248     pdf_add_dict(font->descriptor,
01249                pdf_new_name("Type"), pdf_new_name("FontDescriptor"));
01250   }
01251 
01252   return font->descriptor;
01253 }
01254 
01255 char *
01256 pdf_font_get_usedchars (pdf_font *font)
01257 {
01258   ASSERT(font);
01259 
01260   return font->usedchars;
01261 }
01262 
01263 int
01264 pdf_font_get_encoding (pdf_font *font)
01265 {
01266   ASSERT(font);
01267 
01268   return font->encoding_id;
01269 }
01270 
01271 int
01272 pdf_font_get_flag (pdf_font *font, int mask)
01273 {
01274   ASSERT(font);
01275 
01276   return ((font->flags & mask) ? 1 : 0);
01277 }
01278 
01279 #if 0
01280 int
01281 pdf_font_get_flags (pdf_font *font)
01282 {
01283   ASSERT(font);
01284 
01285   return font->flags;
01286 }
01287 #endif
01288 
01289 double
01290 pdf_font_get_param (pdf_font *font, int param_type)
01291 {
01292   double param = 0.0;
01293 
01294   ASSERT(font);
01295 
01296   switch (param_type) {
01297   case PDF_FONT_PARAM_DESIGN_SIZE:
01298     param = font->design_size;
01299     break;
01300   case PDF_FONT_PARAM_POINT_SIZE:
01301     param = font->point_size;
01302     break;
01303   default:
01304     break;
01305   }
01306 
01307   return param;
01308 }
01309 
01310 char *
01311 pdf_font_get_uniqueTag (pdf_font *font)
01312 {
01313   ASSERT(font);
01314 
01315   if (font->uniqueID[0] == '\0') {
01316     pdf_font_make_uniqueTag(font->uniqueID);
01317   }
01318 
01319   return font->uniqueID;
01320 }
01321 
01322 int
01323 pdf_font_set_fontname (pdf_font *font, const char *fontname)
01324 {
01325   ASSERT(font && fontname);
01326 
01327   if (strlen(fontname) > PDF_NAME_LEN_MAX) {
01328     ERROR("Unexpected error...");
01329     return -1;
01330   }
01331   if (font->fontname) {
01332     RELEASE(font->fontname);
01333   }
01334   font->fontname = NEW(strlen(fontname)+1, char);
01335   strcpy(font->fontname, fontname);
01336 
01337   return 0;
01338 }
01339 
01340 int
01341 pdf_font_set_subtype (pdf_font *font, int subtype)
01342 {
01343   ASSERT(font);
01344 
01345   font->subtype = subtype;
01346 
01347   return 0;
01348 }
01349 
01350 int
01351 pdf_font_set_flags (pdf_font *font, int flags)
01352 {
01353   ASSERT(font);
01354 
01355   font->flags |= flags;
01356 
01357   return 0;
01358 }
01359