Back to index

texmacs  1.0.7.15
type1.c
Go to the documentation of this file.
00001 /*  $Header: /home/cvsroot/dvipdfmx/src/type1.c,v 1.47 2010/02/08 02:51:37 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 <math.h>
00031 
00032 #include "system.h"
00033 #include "mem.h"
00034 #include "error.h"
00035 
00036 #include "dpxfile.h"
00037 
00038 #include "numbers.h"
00039 
00040 #include "pdfobj.h"
00041 #include "pdffont.h"
00042 
00043 #include "pdfencoding.h"
00044 #include "unicode.h"
00045 
00046 #include "dpxutil.h"
00047 
00048 #include "pst_obj.h"
00049 #include "pst.h"
00050 
00051 #include "cff_limits.h"
00052 #include "cff_types.h"
00053 #include "cff_dict.h"
00054 #include "cff.h"
00055 
00056 #include "t1_load.h"
00057 #include "t1_char.h"
00058 
00059 #include "type1.h"
00060 
00061 #include "tfm.h"
00062 
00063 #define FONT_FLAG_FIXEDPITCH (1 << 0)  /* Fixed-width font */
00064 #define FONT_FLAG_SERIF      (1 << 1)  /* Serif font */
00065 #define FONT_FLAG_SYMBOLIC   (1 << 2)  /* Symbolic font */
00066 #define FONT_FLAG_SCRIPT     (1 << 3)  /* Script font */
00067 #define FONT_FLAG_STANDARD   (1 << 5)  /* Adobe Standard Character Set */
00068 #define FONT_FLAG_ITALIC     (1 << 6)  /* Italic */
00069 #define FONT_FLAG_ALLCAP     (1 << 16) /* All-cap font */
00070 #define FONT_FLAG_SMALLCAP   (1 << 17) /* Small-cap font */
00071 #define FONT_FLAG_FORCEBOLD  (1 << 18) /* Force bold at small text sizes */
00072 
00073 static int
00074 is_basefont (const char *name)
00075 {
00076   static const char *basefonts[] = {
00077     "Courier",                  "Courier-Bold",          "Courier-Oblique",
00078     "Courier-BoldOblique",      "Helvetica",             "Helvetica-Bold",
00079     "Helvetica-Oblique",        "Helvetica-BoldOblique", "Symbol",
00080     "Times-Roman",              "Times-Bold",            "Times-Italic",
00081     "Times-BoldItalic",         "ZapfDingbats"
00082   };
00083   int i;
00084 
00085   for (i = 0; i < 14; i++) {
00086     if (!strcmp(name, basefonts[i]))
00087       return 1;
00088   }
00089 
00090   return 0;
00091 }
00092 
00093 int
00094 pdf_font_open_type1 (pdf_font *font)
00095 {
00096   char    *ident;
00097   FILE    *fp;
00098   char     fontname[PDF_NAME_LEN_MAX+1];
00099 
00100   ASSERT(font);
00101 
00102   ident = pdf_font_get_ident(font);
00103 
00104   if (is_basefont(ident)) {
00105     pdf_font_set_fontname(font, ident);
00106     pdf_font_set_subtype (font, PDF_FONT_FONTTYPE_TYPE1);
00107     pdf_font_set_flags   (font,
00108                        (PDF_FONT_FLAG_NOEMBED|PDF_FONT_FLAG_BASEFONT));
00109   } else {
00110     {
00111       char *fontfile =   pdf_font_get_fontfile  (font);
00112 
00113       if (fontfile) {
00114         fp = MFOPEN(fontfile, FOPEN_RBIN_MODE);
00115         if (fp && !is_pfb(fp)) {
00116           DPXFCLOSE(fp);
00117           fp = NULL;
00118         }
00119       }
00120       else
00121         fp = DPXFOPEN(ident, DPX_RES_TYPE_T1FONT);
00122     }
00123     if (!fp)
00124       return -1;
00125 
00126     memset(fontname, 0, PDF_NAME_LEN_MAX+1);
00127     if (!is_pfb(fp) || t1_get_fontname(fp, fontname) < 0) {
00128       ERROR("Failed to read Type 1 font \"%s\".", ident);
00129     }
00130     DPXFCLOSE(fp);
00131 
00132     pdf_font_set_fontname(font, fontname);
00133     pdf_font_set_subtype (font, PDF_FONT_FONTTYPE_TYPE1);
00134   }
00135 
00136   return 0;
00137 }
00138 
00139 static void
00140 get_font_attr (pdf_font *font, cff_font *cffont)
00141 {
00142   char    *fontname;
00143   pdf_obj *descriptor;
00144   double   capheight, ascent, descent;
00145   double   italicangle, stemv;
00146   double   defaultwidth, nominalwidth;
00147   long     flags = 0, gid, i;
00148   static const char *L_c[] = {
00149     "H", "P", "Pi", "Rho", NULL
00150   };
00151   static const char *L_d[] = {
00152     "p", "q", "mu", "eta", NULL
00153   };
00154   static const char *L_a[] = {
00155     "b", "h", "lambda", NULL
00156   };
00157   t1_ginfo gm;
00158 
00159   defaultwidth = 500.0;
00160   nominalwidth = 0.0;
00161 
00162   /*
00163    * CapHeight, Ascent, and Descent is meaningfull only for Latin/Greek/Cyrillic.
00164    * The BlueValues and OtherBlues also have those information.
00165    */
00166   if (cff_dict_known(cffont->topdict, "FontBBox")) {
00167     /* Default values */
00168     capheight = ascent = cff_dict_get(cffont->topdict, "FontBBox", 3);
00169     descent = cff_dict_get(cffont->topdict, "FontBBox", 1);
00170   } else {
00171     capheight =  680.0;
00172     ascent    =  690.0;
00173     descent   = -190.0;
00174   }
00175   if (cff_dict_known(cffont->private[0], "StdVW")) {
00176     stemv = cff_dict_get(cffont->private[0], "StdVW", 0);
00177   } else {
00178     /*
00179      * We may use the following values for StemV:
00180      *  Thin - ExtraLight: <= 50
00181      *  Light: 71
00182      *  Regular(Normal): 88
00183      *  Medium: 109
00184      *  SemiBold(DemiBold): 135
00185      *  Bold - Heavy: >= 166
00186      */
00187     stemv = 88.0;
00188   }
00189   if (cff_dict_known(cffont->topdict, "ItalicAngle")) {
00190     italicangle = cff_dict_get(cffont->topdict, "ItalicAngle", 0);
00191     if (italicangle != 0.0)
00192       flags |= FONT_FLAG_ITALIC;
00193   } else {
00194     italicangle = 0.0;
00195   }
00196 
00197   /*
00198    * Use "space", "H", "p", and "b" for various values.
00199    * Those characters should not "seac". (no accent)
00200    */
00201   gid = cff_glyph_lookup(cffont, "space");
00202   if (gid >= 0 && gid < cffont->cstrings->count) {
00203     t1char_get_metrics(cffont->cstrings->data + cffont->cstrings->offset[gid] - 1,
00204                      cffont->cstrings->offset[gid+1] - cffont->cstrings->offset[gid],
00205                      cffont->subrs[0], &gm);
00206     defaultwidth = gm.wx;
00207   }
00208 
00209   for (i = 0; L_c[i] != NULL; i++) {
00210     gid = cff_glyph_lookup(cffont, L_c[i]);
00211     if (gid >= 0 && gid < cffont->cstrings->count) {
00212       t1char_get_metrics(cffont->cstrings->data + cffont->cstrings->offset[gid] - 1,
00213                     cffont->cstrings->offset[gid+1] - cffont->cstrings->offset[gid],
00214                     cffont->subrs[0], &gm);
00215       capheight = gm.bbox.ury;
00216       break;
00217     }
00218   }
00219 
00220   for (i = 0; L_d[i] != NULL; i++) {
00221     gid = cff_glyph_lookup(cffont, L_d[i]);
00222     if (gid >= 0 && gid < cffont->cstrings->count) {
00223       t1char_get_metrics(cffont->cstrings->data + cffont->cstrings->offset[gid] - 1,
00224                       cffont->cstrings->offset[gid+1] - cffont->cstrings->offset[gid],
00225                       cffont->subrs[0], &gm);
00226       descent = gm.bbox.lly;
00227       break;
00228     }
00229   }
00230 
00231   for (i = 0; L_a[i] != NULL; i++) {
00232     gid = cff_glyph_lookup(cffont, L_a[i]);
00233     if (gid >= 0 && gid < cffont->cstrings->count) {
00234       t1char_get_metrics(cffont->cstrings->data + cffont->cstrings->offset[gid] - 1,
00235                       cffont->cstrings->offset[gid+1] - cffont->cstrings->offset[gid],
00236                       cffont->subrs[0], &gm);
00237       ascent = gm.bbox.ury;
00238       break;
00239     }
00240   }
00241 
00242   if (defaultwidth != 0.0) {
00243     cff_dict_add(cffont->private[0], "defaultWidthX", 1);
00244     cff_dict_set(cffont->private[0], "defaultWidthX", 0, defaultwidth);
00245   }
00246   if (nominalwidth != 0.0) {
00247     cff_dict_add(cffont->private[0], "nominalWidthX", 1);
00248     cff_dict_set(cffont->private[0], "nominalWidthX", 0, nominalwidth);
00249   }
00250   if (cff_dict_known(cffont->private[0], "ForceBold") &&
00251       cff_dict_get(cffont->private[0], "ForceBold", 0)) {
00252     flags |= FONT_FLAG_FORCEBOLD;
00253   }
00254   if (cff_dict_known(cffont->private[0], "IsFixedPitch") &&
00255       cff_dict_get(cffont->private[0], "IsFixedPitch", 0)) {
00256     flags |= FONT_FLAG_FIXEDPITCH;
00257   }
00258 
00259   fontname   = pdf_font_get_fontname  (font);
00260   descriptor = pdf_font_get_descriptor(font);
00261 
00262   if (fontname && !strstr(fontname, "Sans")) {
00263     flags |= FONT_FLAG_SERIF;
00264   }
00265   if (fontname &&  strstr(fontname, "Caps")) {
00266     flags |= FONT_FLAG_SMALLCAP;
00267   }
00268   flags |= FONT_FLAG_SYMBOLIC; /* FIXME */
00269 
00270   pdf_add_dict(descriptor,
00271               pdf_new_name("CapHeight"), pdf_new_number(capheight));
00272   pdf_add_dict(descriptor,
00273               pdf_new_name("Ascent"), pdf_new_number(ascent));
00274   pdf_add_dict(descriptor,
00275               pdf_new_name("Descent"), pdf_new_number(descent));
00276   pdf_add_dict(descriptor,
00277               pdf_new_name("ItalicAngle"), pdf_new_number(italicangle));
00278   pdf_add_dict(descriptor,
00279               pdf_new_name("StemV"), pdf_new_number(stemv));
00280   pdf_add_dict(descriptor,
00281               pdf_new_name("Flags"), pdf_new_number(flags));
00282 }
00283 
00284 static void
00285 add_metrics (pdf_font *font, cff_font *cffont, char **enc_vec, double *widths, long num_glyphs)
00286 {
00287   pdf_obj *fontdict, *descriptor;
00288   pdf_obj *tmp_array;
00289   int      code, firstchar, lastchar;
00290   double   val;
00291   int      i, tfm_id;
00292   char    *usedchars;
00293   double   scaling;
00294 
00295   fontdict   = pdf_font_get_resource  (font);
00296   descriptor = pdf_font_get_descriptor(font);
00297   usedchars  = pdf_font_get_usedchars (font);
00298 
00299   /*
00300    * The original FontBBox of the font is preserved, instead
00301    * of replacing it with tight bounding box calculated from
00302    * charstrings, to prevent Acrobat 4 from greeking text as
00303    * much as possible.
00304    */
00305   if (!cff_dict_known(cffont->topdict, "FontBBox")) {
00306     ERROR("No FontBBox?");
00307   }
00308 
00309   /* The widhts array in the font dictionary must be given relative
00310    * to the default scaling of 1000:1, not relative to the scaling
00311    * given by the font matrix.
00312    */
00313   if (cff_dict_known(cffont->topdict, "FontMatrix"))
00314     scaling = 1000*cff_dict_get(cffont->topdict, "FontMatrix", 0);
00315   else
00316     scaling = 1;
00317 
00318   tmp_array = pdf_new_array();
00319   for (i = 0; i < 4; i++) {
00320     val = cff_dict_get(cffont->topdict, "FontBBox", i);
00321     pdf_add_array(tmp_array, pdf_new_number(ROUND(val, 1.0)));
00322   }
00323   pdf_add_dict(descriptor, pdf_new_name("FontBBox"), tmp_array);
00324 
00325   tmp_array = pdf_new_array();
00326   if (num_glyphs <= 1) { /* This must be an error. */
00327     firstchar = lastchar = 0;
00328     pdf_add_array(tmp_array, pdf_new_number(0.0));
00329   } else {
00330     for (firstchar = 255, lastchar = 0, code = 0; code < 256; code++) {
00331       if (usedchars[code]) {
00332        if (code < firstchar) firstchar = code;
00333        if (code > lastchar)  lastchar  = code;
00334       }
00335     }
00336     if (firstchar > lastchar) {
00337       WARN("No glyphs actually used???");
00338       pdf_release_obj(tmp_array);
00339       return;
00340     }
00341     { 
00342       char *tfmfile = pdf_font_get_tfmfile(font);
00343       if (tfmfile) 
00344         tfm_id = tfm_open(tfmfile, 0); 
00345       else 
00346         tfm_id = tfm_open(pdf_font_get_mapname(font), 0);       
00347     }
00348     for (code = firstchar; code <= lastchar; code++) {
00349       if (usedchars[code]) {
00350         double width;
00351         if (tfm_id < 0) /* tfm is not found */
00352          width = scaling * widths[cff_glyph_lookup(cffont, enc_vec[code])];
00353         else
00354           width = 1000. * tfm_get_width(tfm_id, code);
00355        pdf_add_array(tmp_array,
00356                     pdf_new_number(ROUND(width, 0.1)));
00357       } else {
00358        pdf_add_array(tmp_array, pdf_new_number(0.0));
00359       }
00360     }
00361   }
00362 
00363   if (pdf_array_length(tmp_array) > 0) {
00364     pdf_add_dict(fontdict,
00365                pdf_new_name("Widths"),  pdf_ref_obj(tmp_array));
00366   }
00367   pdf_release_obj(tmp_array);
00368 
00369   pdf_add_dict(fontdict,
00370               pdf_new_name("FirstChar"), pdf_new_number(firstchar));
00371   pdf_add_dict(fontdict,
00372               pdf_new_name("LastChar"),  pdf_new_number(lastchar));
00373 
00374   return;
00375 }
00376 
00377 
00378 static long
00379 write_fontfile (pdf_font *font, cff_font *cffont, long num_glyphs)
00380 {
00381   pdf_obj   *descriptor;
00382   pdf_obj   *fontfile, *stream_dict;
00383   cff_index *topdict;
00384   long       private_size, stream_data_len, charstring_len;
00385   long       topdict_offset, offset;
00386 #define  WBUF_SIZE 1024
00387   card8     *stream_data_ptr, wbuf[WBUF_SIZE];
00388 
00389   descriptor = pdf_font_get_descriptor(font);
00390 
00391   topdict = cff_new_index(1);
00392   /*
00393    * Force existence of Encoding.
00394    */
00395   if (!cff_dict_known(cffont->topdict, "CharStrings"))
00396     cff_dict_add(cffont->topdict, "CharStrings", 1);
00397   if (!cff_dict_known(cffont->topdict, "charset"))
00398     cff_dict_add(cffont->topdict, "charset", 1);
00399   if (!cff_dict_known(cffont->topdict, "Encoding"))
00400     cff_dict_add(cffont->topdict, "Encoding", 1);
00401   private_size = cff_dict_pack((cffont->private)[0], wbuf, WBUF_SIZE);
00402   /* Private dict is required (but may have size 0) */
00403   if (!cff_dict_known(cffont->topdict, "Private"))
00404     cff_dict_add(cffont->topdict, "Private", 2);
00405   topdict->offset[1] = cff_dict_pack(cffont->topdict, wbuf, WBUF_SIZE) + 1;
00406 
00407   /*
00408    * Estimate total size of fontfile.
00409    */
00410   charstring_len = cff_index_size(cffont->cstrings);
00411 
00412   stream_data_len = 4; /* header size */
00413   stream_data_len += cff_index_size(cffont->name);
00414   stream_data_len += cff_index_size(topdict);
00415   stream_data_len += cff_index_size(cffont->string);
00416   stream_data_len += cff_index_size(cffont->gsubr);
00417   /* We are using format 1 for Encoding and format 0 for charset.
00418    * TODO: Should implement cff_xxx_size().
00419    */
00420   stream_data_len += 2 + (cffont->encoding->num_entries)*2 + 1 + (cffont->encoding->num_supps)*3;
00421   stream_data_len += 1 + (cffont->charsets->num_entries)*2;
00422   stream_data_len += charstring_len;
00423   stream_data_len += private_size;
00424 
00425   /*
00426    * Now we create FontFile data.
00427    */
00428   stream_data_ptr = NEW(stream_data_len, card8);
00429   /*
00430    * Data Layout order as described in CFF spec., sec 2 "Data Layout".
00431    */
00432   offset = 0;
00433   /* Header */
00434   offset += cff_put_header(cffont,
00435                         stream_data_ptr + offset, stream_data_len - offset);
00436   /* Name */
00437   offset += cff_pack_index(cffont->name,
00438                         stream_data_ptr + offset, stream_data_len - offset);
00439   /* Top DICT */
00440   topdict_offset = offset;
00441   offset += cff_index_size(topdict);
00442   /* Strings */
00443   offset += cff_pack_index(cffont->string,
00444                         stream_data_ptr + offset, stream_data_len - offset);
00445   /* Global Subrs */
00446   offset += cff_pack_index(cffont->gsubr,
00447                         stream_data_ptr + offset, stream_data_len - offset);
00448   /* Encoding */
00449   /* TODO: don't write Encoding entry if the font is always used
00450    * with PDF Encoding information. Applies to type1c.c as well.
00451    */
00452   cff_dict_set(cffont->topdict, "Encoding", 0, offset);
00453   offset += cff_pack_encoding(cffont,
00454                            stream_data_ptr + offset, stream_data_len - offset);
00455   /* charset */
00456   cff_dict_set(cffont->topdict, "charset", 0, offset);
00457   offset += cff_pack_charsets(cffont,
00458                            stream_data_ptr + offset, stream_data_len - offset);
00459   /* CharStrings */
00460   cff_dict_set(cffont->topdict, "CharStrings", 0, offset);
00461   offset += cff_pack_index(cffont->cstrings,
00462                         stream_data_ptr + offset, charstring_len);
00463   /* Private */
00464   if ((cffont->private)[0] && private_size > 0) {
00465     private_size = cff_dict_pack(cffont->private[0],
00466                              stream_data_ptr + offset, private_size);
00467     cff_dict_set(cffont->topdict, "Private", 1, offset);
00468     cff_dict_set(cffont->topdict, "Private", 0, private_size);
00469   }
00470   offset += private_size;
00471 
00472   /* Finally Top DICT */
00473   topdict->data = NEW(topdict->offset[1] - 1, card8);
00474   cff_dict_pack (cffont->topdict, topdict->data, topdict->offset[1] - 1);
00475   cff_pack_index(topdict,
00476                stream_data_ptr + topdict_offset, cff_index_size(topdict));
00477   cff_release_index(topdict);
00478 
00479   /* Copyright and Trademark Notice ommited. */
00480 
00481   /* Flush Font File */
00482   fontfile    = pdf_new_stream(STREAM_COMPRESS);
00483   stream_dict = pdf_stream_dict(fontfile);
00484   pdf_add_dict(descriptor,
00485               pdf_new_name("FontFile3"), pdf_ref_obj (fontfile));
00486   pdf_add_dict(stream_dict,
00487               pdf_new_name("Subtype"),   pdf_new_name("Type1C"));
00488   pdf_add_stream (fontfile, (void *) stream_data_ptr,  offset);
00489   pdf_release_obj(fontfile);
00490 
00491   RELEASE(stream_data_ptr);
00492 
00493   return offset;
00494 }
00495 
00496 
00497 int
00498 pdf_font_load_type1 (pdf_font *font)
00499 {
00500   pdf_obj      *fontdict, *descriptor;
00501   int           encoding_id;
00502   char         *usedchars, *ident;
00503   char         *fontname, *uniqueTag, *fontfile;
00504   char         *fullname; /* With pseudo unique tag */
00505   cff_font     *cffont;
00506   cff_charsets *charset;
00507   char        **enc_vec;
00508   double        defaultwidth, nominalwidth;
00509   double       *widths;
00510   card16       *GIDMap, num_glyphs = 0;
00511   FILE         *fp;
00512   long          offset;
00513   int           code, verbose;
00514 
00515   ASSERT(font);
00516 
00517   if (!pdf_font_is_in_use(font)) {
00518     return 0;
00519   }
00520 
00521   verbose     = pdf_font_get_verbose();
00522 
00523   encoding_id = pdf_font_get_encoding  (font);
00524   fontdict    = pdf_font_get_resource  (font);
00525 
00526   descriptor  = pdf_font_get_descriptor(font);
00527   usedchars   = pdf_font_get_usedchars (font);
00528   ident       = pdf_font_get_ident     (font);
00529   fontname    = pdf_font_get_fontname  (font);
00530   fontfile    = pdf_font_get_fontfile  (font);
00531   uniqueTag   = pdf_font_get_uniqueTag (font);
00532   if (!usedchars || !ident || !fontname) {
00533     ERROR("Type1: Unexpected error.");
00534   }
00535 
00536   
00537   if (fontfile)
00538     fp = MFOPEN(fontfile, FOPEN_RBIN_MODE);
00539   else
00540     fp = DPXFOPEN(ident, DPX_RES_TYPE_T1FONT);
00541   
00542   if (!fp) {
00543     ERROR("Type1: Could not open Type1 font: %s", ident);
00544   }
00545 
00546   GIDMap     = NULL;
00547   num_glyphs = 0;
00548 
00549   if (encoding_id >= 0) {
00550     enc_vec = NULL;
00551   } else {
00552     enc_vec = NEW(256, char *);
00553     for (code = 0; code <= 0xff; code++) {
00554       enc_vec[code] = NULL;
00555     }
00556   }
00557 
00558   cffont = t1_load_font(enc_vec, 0, fp);
00559   if (!cffont) {
00560     ERROR("Could not load Type 1 font: %s", ident);
00561   }
00562   DPXFCLOSE(fp);
00563 
00564   fullname = NEW(strlen(fontname) + 8, char);
00565   sprintf(fullname, "%6s+%s", uniqueTag, fontname);
00566 
00567   /*
00568    * Encoding related things.
00569    */
00570   if (encoding_id >= 0) {
00571     enc_vec = pdf_encoding_get_encoding(encoding_id);
00572   } else {
00573     pdf_obj *tounicode;
00574 
00575     /*
00576      * Create enc_vec and ToUnicode CMap for built-in encoding.
00577      */
00578     if (!pdf_lookup_dict(fontdict, "ToUnicode")) {
00579     tounicode = pdf_create_ToUnicode_CMap(fullname,
00580                                      enc_vec, usedchars);
00581     if (tounicode) {
00582       pdf_add_dict(fontdict,
00583                      pdf_new_name("ToUnicode"),
00584                      pdf_ref_obj (tounicode));
00585       pdf_release_obj(tounicode);
00586       }
00587     }
00588   }
00589 
00590   cff_set_name(cffont, fullname);
00591   RELEASE(fullname);
00592 
00593   /* defaultWidthX, CapHeight, etc. */
00594   get_font_attr(font, cffont);
00595   if (cff_dict_known(cffont->private[0], "defaultWidthX")) {
00596     defaultwidth = cff_dict_get(cffont->private[0], "defaultWidthX", 0);
00597   } else {
00598     defaultwidth = 0.0;
00599   }
00600   if (cff_dict_known(cffont->private[0], "nominalWidthX")) {
00601     nominalwidth = cff_dict_get(cffont->private[0], "nominalWidthX", 0);
00602   } else {
00603     nominalwidth = 0.0;
00604   }
00605 
00606   /* Create CFF encoding, charset, sort glyphs */
00607 #define MAX_GLYPHS 1024
00608   GIDMap = NEW(MAX_GLYPHS, card16);
00609   {
00610     int     prev, duplicate;
00611     long    gid;
00612     char   *glyph;
00613     s_SID   sid;
00614 
00615     cffont->encoding = NEW(1, cff_encoding);
00616     cffont->encoding->format      = 1;
00617     cffont->encoding->num_entries = 0;
00618     cffont->encoding->data.range1 = NEW(256, cff_range1);
00619     cffont->encoding->num_supps   = 0;
00620     cffont->encoding->supp        = NEW(256, cff_map);
00621 
00622     charset = NEW(1, cff_charsets);
00623     charset->format      = 0;
00624     charset->num_entries = 0;
00625     charset->data.glyphs = NEW(MAX_GLYPHS, s_SID);
00626 
00627     gid = cff_glyph_lookup(cffont, ".notdef");
00628     if (gid < 0)
00629       ERROR("Type 1 font with no \".notdef\" glyph???");
00630     GIDMap[0] = (card16) gid;
00631     if (verbose > 2)
00632       MESG("[glyphs:/.notdef");
00633     num_glyphs =  1;
00634     for (prev = -2, code = 0; code <= 0xff; code++) {
00635       glyph = enc_vec[code];
00636 
00637       if (!usedchars[code])
00638        continue;
00639       if (glyph && !strcmp(glyph, ".notdef")) {
00640        WARN("Character mapped to .notdef used in font: %s",
00641             fontname);
00642        usedchars[code] = 0;
00643        continue;
00644       }
00645 
00646       gid = cff_glyph_lookup(cffont, glyph);
00647       if (gid < 1 || gid >= cffont->cstrings->count) {
00648        WARN("Glyph \"%s\" missing in font \"%s\".", glyph, fontname);
00649        usedchars[code] = 0;
00650        continue;
00651       }
00652 
00653       for (duplicate = 0; duplicate < code; duplicate++) {
00654        if (usedchars[duplicate] &&
00655            enc_vec[duplicate]   && !strcmp(enc_vec[duplicate], glyph))
00656          break;
00657       }
00658 
00659       sid = cff_add_string(cffont, glyph, 1); /* FIXME */
00660       if (duplicate < code) { /* found duplicates */
00661        cffont->encoding->supp[cffont->encoding->num_supps].code  = duplicate;
00662        cffont->encoding->supp[cffont->encoding->num_supps].glyph = sid;
00663        cffont->encoding->num_supps += 1;
00664       } else {
00665        GIDMap[num_glyphs] = (card16) gid;
00666        charset->data.glyphs[charset->num_entries] = sid;
00667        charset->num_entries += 1;
00668        if (code != prev + 1) {
00669          cffont->encoding->num_entries += 1;
00670          cffont->encoding->data.range1[cffont->encoding->num_entries-1].first  = code;
00671          cffont->encoding->data.range1[cffont->encoding->num_entries-1].n_left = 0;
00672        } else {
00673          cffont->encoding->data.range1[cffont->encoding->num_entries-1].n_left += 1;
00674        }
00675        prev = code;
00676        num_glyphs++;
00677 
00678        if (verbose > 2) {
00679          MESG("/%s", glyph);
00680        }
00681 
00682       }
00683     }
00684     if (cffont->encoding->num_supps > 0) {
00685       cffont->encoding->format |= 0x80;
00686     } else {
00687       RELEASE(cffont->encoding->supp); /* FIXME */
00688       cffont->encoding->supp = NULL;
00689     }
00690   }
00691 
00692   widths = NEW(cffont->cstrings->count, double);
00693   /*
00694    * No more string will be added.
00695    * The Type 1 seac operator may add another glyph but the glyph name of
00696    * those glyphs are contained in standard string. The String Index will
00697    * not be modified after here.
00698    * BUT: We cannot update the String Index yet because then we wouldn't be
00699    * able to find the GIDs of the base and accent characters (unless they
00700    * have been used already).
00701    */
00702 
00703   {
00704     cff_index *cstring;
00705     t1_ginfo   gm;
00706     card16     gid, gid_orig;
00707     long       dstlen_max, srclen;
00708     int        have_seac = 0;
00709     card8     *srcptr, *dstptr;
00710 
00711     offset  = dstlen_max = 0L;
00712     cstring = cff_new_index(cffont->cstrings->count);
00713     cstring->data      = NULL;
00714     cstring->offset[0] = 1;
00715     
00716     /* The num_glyphs increases if "seac" operators are used. */
00717     for (gid = 0; gid < num_glyphs; gid++) {
00718       if (offset + CS_STR_LEN_MAX >= dstlen_max) {
00719        dstlen_max += CS_STR_LEN_MAX * 2;
00720        cstring->data = RENEW(cstring->data, dstlen_max, card8);
00721       }
00722       gid_orig = GIDMap[gid];
00723 
00724       dstptr   = cstring->data + cstring->offset[gid] - 1;
00725       srcptr   = cffont->cstrings->data + cffont->cstrings->offset[gid_orig] - 1;
00726       srclen   = cffont->cstrings->offset[gid_orig + 1] - cffont->cstrings->offset[gid_orig];
00727 
00728       offset  += t1char_convert_charstring(dstptr, CS_STR_LEN_MAX,
00729                                       srcptr, srclen,
00730                                       cffont->subrs[0], defaultwidth, nominalwidth, &gm);
00731       cstring->offset[gid + 1] = offset + 1;
00732       if (gm.use_seac) {
00733        long  bchar_gid, achar_gid, i;
00734        char *bchar_name, *achar_name;
00735 
00736        /*
00737         * NOTE:
00738         *  1. seac.achar and seac.bchar must be contained in the CFF standard string.
00739         *  2. Those characters need not to be encoded.
00740         *  3. num_glyphs == charsets->num_entries + 1.
00741         */
00742        achar_name = t1_get_standard_glyph(gm.seac.achar);
00743        achar_gid  = cff_glyph_lookup(cffont, achar_name);
00744        bchar_name = t1_get_standard_glyph(gm.seac.bchar);
00745        bchar_gid  = cff_glyph_lookup(cffont, bchar_name);
00746        if (achar_gid < 0) {
00747          WARN("Accent char \"%s\" not found. Invalid use of \"seac\" operator.",
00748               achar_name);
00749          continue;
00750        }
00751        if (bchar_gid < 0) {
00752          WARN("Base char \"%s\" not found. Invalid use of \"seac\" operator.",
00753               bchar_name);
00754          continue;
00755        }
00756 
00757        for (i = 0; i < num_glyphs; i++) {
00758          if (GIDMap[i] == achar_gid)
00759            break;
00760        }
00761        if (i == num_glyphs) {
00762          if (verbose > 2)
00763            MESG("/%s", achar_name);
00764          GIDMap[num_glyphs++] = achar_gid;
00765          charset->data.glyphs[charset->num_entries] = cff_get_sid(cffont, achar_name);
00766          charset->num_entries += 1;
00767        }
00768 
00769        for (i = 0; i < num_glyphs; i++) {
00770          if (GIDMap[i] == bchar_gid)
00771            break;
00772        }
00773        if (i == num_glyphs) {
00774          if (verbose > 2)
00775            MESG("/%s", bchar_name);
00776          GIDMap[num_glyphs++] = bchar_gid;
00777          charset->data.glyphs[charset->num_entries] = cff_get_sid(cffont, bchar_name);
00778          charset->num_entries += 1;
00779        }
00780        have_seac = 1;
00781       }
00782       widths[gid] = gm.wx;
00783     }
00784     cstring->count = num_glyphs;
00785 
00786     cff_release_index(cffont->subrs[0]);
00787     cffont->subrs[0] = NULL;
00788     RELEASE(cffont->subrs);
00789     cffont->subrs    = NULL;
00790 
00791     cff_release_index(cffont->cstrings);
00792     cffont->cstrings = cstring;
00793 
00794     cff_release_charsets(cffont->charsets);
00795     cffont->charsets = charset;
00796   }
00797   if (verbose > 2)
00798     MESG("]");
00799 
00800   /* Now we can update the String Index */
00801   cff_dict_update  (cffont->topdict,    cffont);
00802   cff_dict_update  (cffont->private[0], cffont);
00803   cff_update_string(cffont);
00804 
00805   add_metrics(font, cffont, enc_vec, widths, num_glyphs);
00806 
00807   offset = write_fontfile(font, cffont, num_glyphs);
00808   if (verbose > 1)
00809     MESG("[%u glyphs][%ld bytes]", num_glyphs, offset);
00810 
00811   cff_close(cffont);
00812 
00813   /* Cleanup */
00814   if (encoding_id < 0 && enc_vec) {
00815     for (code = 0; code < 256; code++) {
00816       if (enc_vec[code])
00817        RELEASE(enc_vec[code]);
00818       enc_vec[code] = NULL;
00819     }
00820     RELEASE(enc_vec);
00821   }
00822   if (widths)
00823     RELEASE(widths);
00824   if (GIDMap)
00825     RELEASE(GIDMap);
00826 
00827   /*
00828    * Maybe writing Charset is recommended for subsetted font.
00829    */
00830 
00831   return 0;
00832 }