Back to index

texmacs  1.0.7.15
type1c.c
Go to the documentation of this file.
00001 /*  $Header: /home/cvsroot/dvipdfmx/src/type1c.c,v 1.30 2009/08/28 00:26:17 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 /*
00026  * CFF/OpenType Font support:
00027  *
00028  *  Adobe Technical Note #5176, "The Compact Font Format Specfication"
00029  *
00030  * NOTE:
00031  *
00032  *  Many CFF/OpenType does not have meaningful/correct CFF encoding.
00033  *  Encoding should be expilicitly supplied in the fontmap.
00034  *
00035  */ 
00036 
00037 #if HAVE_CONFIG_H
00038 #include "config.h"
00039 #endif
00040 
00041 #include <string.h>
00042 
00043 #include "system.h"
00044 #include "mem.h"
00045 #include "error.h"
00046 
00047 #include "dpxfile.h"
00048 
00049 #include "pdfobj.h"
00050 #include "pdffont.h"
00051 
00052 #include "pdfencoding.h"
00053 #include "unicode.h"
00054 
00055 /* Font info. from OpenType tables */
00056 #include "sfnt.h"
00057 #include "tt_aux.h"
00058 
00059 #include "cff_types.h"
00060 #include "cff_limits.h"
00061 #include "cff.h"
00062 #include "cff_dict.h"
00063 #include "cs_type2.h"
00064 
00065 #include "type1c.h"
00066 
00067 #include "tfm.h"
00068 
00069 int
00070 pdf_font_open_type1c (pdf_font *font)
00071 {
00072   char     *ident, *fontname;
00073   FILE     *fp;
00074   sfnt     *sfont;
00075   cff_font *cffont;
00076   pdf_obj  *descriptor, *tmp;
00077   unsigned long offset = 0;
00078   int       encoding_id, embedding;
00079 
00080   ASSERT(font);
00081 
00082   ident       = pdf_font_get_ident   (font);
00083   encoding_id = pdf_font_get_encoding(font);
00084 
00085   fp = DPXFOPEN(ident, DPX_RES_TYPE_OTFONT);
00086   if (!fp)
00087     return -1;
00088 
00089   sfont = sfnt_open(fp);
00090   if (!sfont ||
00091       sfont->type != SFNT_TYPE_POSTSCRIPT     ||
00092       sfnt_read_table_directory(sfont, 0) < 0) {
00093     ERROR("Not a CFF/OpenType font?");
00094   }
00095 
00096   offset = sfnt_find_table_pos(sfont, "CFF ");
00097   if (offset < 1) {
00098     ERROR("No \"CFF \" table found. Not a CFF/OpenType font?");
00099   }
00100 
00101   cffont = cff_open(sfont->stream, offset, 0);
00102   if (!cffont) {
00103     ERROR("Could not read CFF font data");
00104   }
00105 
00106   if (cffont->flag & FONTTYPE_CIDFONT) {
00107     cff_close (cffont);
00108     sfnt_close(sfont);
00109     DPXFCLOSE(fp);
00110     return -1;
00111   }
00112 
00113   fontname = cff_get_name(cffont);
00114   if (!fontname) {
00115     ERROR("No valid FontName found in CFF/OpenType font.");
00116   }
00117   pdf_font_set_fontname(font, fontname);
00118   RELEASE(fontname);
00119 
00120   cff_close(cffont);
00121 
00122   /*
00123    * Font like AdobePiStd does not have meaningful built-in encoding.
00124    * Some software generate CFF/OpenType font with incorrect encoding.
00125    */
00126   if (encoding_id < 0) {
00127     WARN("Built-in encoding used for CFF/OpenType font.");
00128     WARN("CFF font in OpenType font sometimes have strange built-in encoding.");
00129     WARN("If you find text is not encoded properly in the generated PDF file,");
00130     WARN("please specify appropriate \".enc\" file in your fontmap.");
00131   }
00132   pdf_font_set_subtype (font, PDF_FONT_FONTTYPE_TYPE1C);
00133 
00134   embedding  = pdf_font_get_flag(font, PDF_FONT_FLAG_NOEMBED) ? 0 : 1;
00135   descriptor = pdf_font_get_descriptor(font);
00136   /*
00137    * Create font descriptor from OpenType tables.
00138    * We can also use CFF TOP DICT/Private DICT for this.
00139    */
00140   tmp = tt_get_fontdesc(sfont, &embedding, -1, 1);
00141   if (!tmp) {
00142     ERROR("Could not obtain neccesary font info from OpenType table.");
00143     return -1;
00144   }
00145   pdf_merge_dict (descriptor, tmp); /* copy */
00146   pdf_release_obj(tmp);
00147   if (!embedding) { /* tt_get_fontdesc may have changed this */
00148     pdf_font_set_flags(font, PDF_FONT_FLAG_NOEMBED);
00149   }
00150 
00151   sfnt_close(sfont);
00152   DPXFCLOSE(fp);
00153 
00154   return 0;
00155 }
00156 
00157 static void
00158 add_SimpleMetrics (pdf_font *font, cff_font *cffont,
00159                  double *widths, card16 num_glyphs)
00160 {
00161   pdf_obj *fontdict;
00162   int      code, firstchar, lastchar, tfm_id;
00163   char    *usedchars;
00164   pdf_obj *tmp_array;
00165   double   scaling;
00166 
00167   fontdict  = pdf_font_get_resource(font);
00168   usedchars = pdf_font_get_usedchars(font);
00169 
00170   /* The widhts array in the font dictionary must be given relative
00171    * to the default scaling of 1000:1, not relative to the scaling
00172    * given by the font matrix.
00173    */
00174   if (cff_dict_known(cffont->topdict, "FontMatrix"))
00175     scaling = 1000*cff_dict_get(cffont->topdict, "FontMatrix", 0);
00176   else
00177     scaling = 1;
00178 
00179   tmp_array = pdf_new_array();
00180   if (num_glyphs <= 1) {
00181     /* This should be error. */
00182     firstchar = lastchar = 0;
00183     pdf_add_array(tmp_array, pdf_new_number(0.0));
00184   } else {
00185     firstchar = 255; lastchar = 0;
00186     for (code = 0; code < 256; code++) {
00187       if (usedchars[code]) {
00188        if (code < firstchar) firstchar = code;
00189        if (code > lastchar)  lastchar  = code;
00190       }
00191     }
00192     if (firstchar > lastchar) {
00193       ERROR("No glyphs used at all!");
00194       pdf_release_obj(tmp_array);
00195       return;
00196     }
00197     { 
00198       char *tfmfile = pdf_font_get_tfmfile(font);
00199       if (tfmfile) 
00200         tfm_id = tfm_open(tfmfile, 0); 
00201       else 
00202         tfm_id = tfm_open(pdf_font_get_mapname(font), 0);       
00203     }
00204     for (code = firstchar; code <= lastchar; code++) {
00205       if (usedchars[code]) {
00206         double width;
00207         if (tfm_id < 0) /* tfm is not found */
00208           width = scaling * widths[code];
00209         else
00210           width = 1000. * tfm_get_width(tfm_id, code);
00211        pdf_add_array(tmp_array,
00212                     pdf_new_number(ROUND(width, 0.1)));
00213       } else {
00214        pdf_add_array(tmp_array, pdf_new_number(0.0));
00215       }
00216     }
00217   }
00218 
00219   if (pdf_array_length(tmp_array) > 0) {
00220     pdf_add_dict(fontdict,
00221                pdf_new_name("Widths"),  pdf_ref_obj(tmp_array));
00222   }
00223   pdf_release_obj(tmp_array);
00224 
00225   pdf_add_dict(fontdict,
00226               pdf_new_name("FirstChar"), pdf_new_number(firstchar));
00227   pdf_add_dict(fontdict,
00228               pdf_new_name("LastChar"),  pdf_new_number(lastchar));
00229 
00230   return;
00231 }
00232 
00233 int
00234 pdf_font_load_type1c (pdf_font *font)
00235 {
00236   pdf_obj      *fontdict, *descriptor;
00237   char         *usedchars;
00238   char         *fontname, *uniqueTag, *ident, *fullname;
00239   FILE         *fp;
00240   int           encoding_id;
00241   pdf_obj      *fontfile, *stream_dict;
00242   char        **enc_vec;
00243   sfnt         *sfont;
00244   cff_font     *cffont;
00245   cff_index    *charstrings, *topdict, *cs_idx;
00246   cff_charsets *charset  = NULL;
00247   cff_encoding *encoding = NULL;
00248   long          topdict_offset, private_size;
00249   long          charstring_len, max_len;
00250   long          size, offset = 0;
00251   long          stream_data_len = 0;
00252   card8        *stream_data_ptr, *data;
00253   card16        num_glyphs, cs_count, code;
00254   cs_ginfo      ginfo;
00255   double        nominal_width, default_width, notdef_width;
00256   double        widths[256];
00257   int           verbose;
00258 
00259   ASSERT(font);
00260 
00261   verbose = pdf_font_get_verbose();
00262 
00263   if (!pdf_font_is_in_use(font)) {
00264     return 0;
00265   }
00266 
00267   if (pdf_font_get_flag(font, PDF_FONT_FLAG_NOEMBED)) {
00268     ERROR("Only embedded font supported for CFF/OpenType font.");
00269   }
00270 
00271   usedchars = pdf_font_get_usedchars (font);
00272   fontname  = pdf_font_get_fontname  (font);
00273   ident     = pdf_font_get_ident     (font);
00274   uniqueTag = pdf_font_get_uniqueTag (font);
00275   if (!usedchars ||
00276       !fontname  || !ident) {
00277     ERROR("Unexpected error....");
00278   }
00279 
00280   fontdict    = pdf_font_get_resource  (font);
00281   descriptor  = pdf_font_get_descriptor(font);
00282   encoding_id = pdf_font_get_encoding  (font);
00283 
00284   fp = DPXFOPEN(ident, DPX_RES_TYPE_OTFONT);
00285   if (!fp) {
00286     ERROR("Could not open OpenType font: %s", ident);
00287   }
00288 
00289   sfont = sfnt_open(fp);
00290   if (!sfont) {
00291     ERROR("Could not open OpenType font: %s", ident);
00292   }
00293   if (sfnt_read_table_directory(sfont, 0) < 0) {
00294     ERROR("Could not read OpenType table directory: %s", ident);
00295   }
00296   if (sfont->type != SFNT_TYPE_POSTSCRIPT ||
00297       (offset = sfnt_find_table_pos(sfont, "CFF ")) == 0) {
00298     ERROR("Not a CFF/OpenType font ?");
00299   }
00300 
00301   cffont = cff_open(fp, offset, 0);
00302   if (!cffont) {
00303     ERROR("Could not open CFF font.");
00304   }
00305   if (cffont->flag & FONTTYPE_CIDFONT) {
00306     ERROR("This is CIDFont...");
00307   }
00308 
00309   fullname = NEW(strlen(fontname) + 8, char);
00310   sprintf(fullname, "%6s+%s", uniqueTag, fontname);
00311 
00312   /* Offsets from DICTs */
00313   cff_read_charsets(cffont);
00314   if (encoding_id < 0)
00315     cff_read_encoding(cffont);
00316   cff_read_private(cffont);
00317   cff_read_subrs  (cffont);
00318 
00319   /* FIXME */
00320   cffont->_string = cff_new_index(0);
00321 
00322   /* New Charsets data */
00323   charset = NEW(1, cff_charsets);
00324   charset->format      = 0;
00325   charset->num_entries = 0;
00326   charset->data.glyphs = NEW(256, s_SID);
00327 
00328   /*
00329    * Encoding related things.
00330    */
00331   enc_vec = NULL;
00332   if (encoding_id >= 0) {
00333     enc_vec = pdf_encoding_get_encoding(encoding_id);
00334   } else {
00335     pdf_obj *tounicode;
00336 
00337     /*
00338      * Create enc_vec and ToUnicode CMap for built-in encoding.
00339      */
00340     enc_vec = NEW(256, char *);
00341     for (code = 0; code < 256; code++) {
00342       if (usedchars[code]) {
00343        card16  gid;
00344 
00345        gid = cff_encoding_lookup(cffont, code);
00346        enc_vec[code] = cff_get_string(cffont,
00347                                    cff_charsets_lookup_inverse(cffont, gid));
00348       } else {
00349        enc_vec[code] = NULL;
00350       }
00351     }
00352     if (!pdf_lookup_dict(fontdict, "ToUnicode")) {
00353       tounicode = pdf_create_ToUnicode_CMap(fullname,
00354                                        enc_vec, usedchars);
00355       if (tounicode) {
00356        pdf_add_dict(fontdict,
00357                      pdf_new_name("ToUnicode"),
00358                      pdf_ref_obj (tounicode));
00359        pdf_release_obj(tounicode);
00360       }
00361     }
00362   }
00363 
00364   /*
00365    * New Encoding data:
00366    *
00367    *  We should not use format 0 here.
00368    *  The number of encoded glyphs (num_entries) is limited to 255 in format 0,
00369    *  and hence it causes problem for encodings that uses full 256 code-points.
00370    *  As we always sort glyphs by encoding, we can avoid this problem simply
00371    *  by using format 1; Using full range result in a single range, 0 255.
00372    *
00373    *  Creating actual encoding date is delayed to eliminate character codes to
00374    *  be mapped to .notdef and to handle multiply-encoded glyphs.
00375    */
00376   encoding = NEW(1, cff_encoding);
00377   encoding->format      = 1;
00378   encoding->num_entries = 0;
00379   encoding->data.range1 = NEW(255, cff_range1);
00380   encoding->num_supps   = 0;
00381   encoding->supp        = NEW(255, cff_map);
00382 
00383   /*
00384    * Charastrings.
00385    */
00386   offset = (long) cff_dict_get(cffont->topdict, "CharStrings", 0);
00387   cff_seek_set(cffont, offset);
00388   cs_idx = cff_get_index_header(cffont);
00389 
00390   /* Offset is now absolute offset ... fixme */
00391   offset   = ftell(cffont->stream);
00392   cs_count = cs_idx->count;
00393   if (cs_count < 2) {
00394     ERROR("No valid charstring data found.");
00395   }
00396 
00397   /* New CharStrings INDEX */
00398   charstrings       = cff_new_index(257);   /* 256 + 1 for ".notdef" glyph */
00399   max_len           = 2 * CS_STR_LEN_MAX;
00400   charstrings->data = NEW(max_len, card8);
00401   charstring_len    = 0;
00402 
00403   /*
00404    * Information from OpenType table is rough estimate. Replace with accurate value.
00405    */
00406   if (cffont->private[0] &&
00407       cff_dict_known(cffont->private[0], "StdVW")) {
00408     double stemv;
00409 
00410     stemv = cff_dict_get(cffont->private[0], "StdVW", 0);
00411     pdf_add_dict(descriptor,
00412                pdf_new_name("StemV"), pdf_new_number(stemv));
00413   }
00414   
00415   /*
00416    * Widths
00417    */
00418   if (cffont->private[0] &&
00419       cff_dict_known(cffont->private[0], "defaultWidthX")) {
00420     default_width = (double) cff_dict_get(cffont->private[0], "defaultWidthX", 0);
00421   } else {
00422     default_width = CFF_DEFAULTWIDTHX_DEFAULT;
00423   }
00424   if (cffont->private[0] &&
00425       cff_dict_known(cffont->private[0], "nominalWidthX")) {
00426     nominal_width = (double) cff_dict_get(cffont->private[0], "nominalWidthX", 0);
00427   } else {
00428     nominal_width = CFF_NOMINALWIDTHX_DEFAULT;
00429   }
00430 
00431   data = NEW(CS_STR_LEN_MAX, card8);
00432 
00433   /* First we add .notdef glyph.
00434    * All Type 1 font requires .notdef glyph to be present.
00435    */
00436   if (verbose > 2) {
00437     MESG("[glyphs:/.notdef");
00438   }
00439   size = cs_idx->offset[1] - cs_idx->offset[0];
00440   if (size > CS_STR_LEN_MAX) {
00441     ERROR("Charstring too long: gid=%u, %ld bytes", 0, size);
00442   }
00443   charstrings->offset[0] = charstring_len + 1;
00444   seek_absolute(cffont->stream, offset + cs_idx->offset[0] - 1);
00445   fread(data, 1, size, cffont->stream);
00446   charstring_len += cs_copy_charstring(charstrings->data + charstring_len,
00447                                    max_len - charstring_len,
00448                                    data, size,
00449                                    cffont->gsubr, cffont->subrs[0],
00450                                    default_width, nominal_width, &ginfo);
00451   notdef_width = ginfo.wx;
00452 
00453   /*
00454    * Subset font
00455    */
00456   num_glyphs = 1;
00457   for (code = 0; code < 256; code++) {
00458     card16 gid, j;
00459     s_SID  sid_orig, sid;
00460 
00461     widths[code] = notdef_width;
00462 
00463     if (!usedchars[code] || !enc_vec[code] ||
00464        !strcmp(enc_vec[code], ".notdef"))
00465       continue;
00466 
00467     /*
00468      * FIXME:
00469      *  cff_get_sid() obtain SID from original String INDEX.
00470      *  It should be cff_string_get_sid(string, ...).
00471      *  cff_add_string(cff, ...) -> cff_string_add(string, ...).
00472      */
00473     sid_orig = cff_get_sid   (cffont, enc_vec[code]);
00474     sid      = sid_orig < CFF_STDSTR_MAX ?
00475                  sid_orig : cff_add_string(cffont, enc_vec[code], 0);
00476     /*
00477      * We use "unique = 0" because duplicate strings are impossible
00478      * at this stage unless the original font already had duplicates.
00479      */
00480 
00481     /*
00482      * Check if multiply-encoded glyph.
00483      */
00484     for (j = 0; j < charset->num_entries; j++) {
00485       if (sid == charset->data.glyphs[j]) {
00486        /* Already have this glyph. */
00487        encoding->supp[encoding->num_supps].code  = code;
00488        encoding->supp[encoding->num_supps].glyph = sid;
00489        usedchars[code] = 0; /* Used but multiply-encoded. */
00490        encoding->num_supps += 1;
00491        break;
00492       }
00493     }
00494     if (j < charset->num_entries) {
00495       continue; /* Prevent duplication. */
00496     }
00497 
00498     /* This is new encoding entry. */
00499     gid = cff_charsets_lookup(cffont, sid_orig); /* FIXME */
00500     if (gid == 0) {
00501       WARN("Glyph \"%s\" missing in font \"%s\".", enc_vec[code], fontname);
00502       WARN("Maybe incorrect encoding specified.");
00503       usedchars[code] = 0; /* Set unused for writing correct encoding */
00504       continue;
00505     }
00506     if (verbose > 2) {
00507       MESG("/%s", enc_vec[code]);
00508     }
00509 
00510     size = cs_idx->offset[gid+1] - cs_idx->offset[gid];
00511     if (size > CS_STR_LEN_MAX) {
00512       ERROR("Charstring too long: gid=%u, %ld bytes", gid, size);
00513     }
00514 
00515     if (charstring_len + CS_STR_LEN_MAX >= max_len) {
00516       max_len = charstring_len + 2 * CS_STR_LEN_MAX;
00517       charstrings->data = RENEW(charstrings->data, max_len, card8);
00518     }
00519     charstrings->offset[num_glyphs] = charstring_len + 1;
00520     seek_absolute(cffont->stream, offset + cs_idx->offset[gid] - 1);
00521     fread(data, sizeof(char), size, cffont->stream);
00522     charstring_len += cs_copy_charstring(charstrings->data + charstring_len,
00523                                     max_len - charstring_len,
00524                                     data, size,
00525                                     cffont->gsubr, cffont->subrs[0],
00526                                     default_width, nominal_width, &ginfo);
00527     widths[code] = ginfo.wx;
00528     charset->data.glyphs[charset->num_entries] = sid;
00529     charset->num_entries  += 1;
00530     num_glyphs++;
00531   }
00532   if (verbose > 2) {
00533     MESG("]");
00534   }
00535   RELEASE(data);
00536 
00537   /*
00538    * Now we create encoding data.
00539    */
00540   if (encoding->num_supps > 0)
00541     encoding->format |= 0x80; /* Have supplemantary data. */
00542   else {
00543     RELEASE(encoding->supp); /* FIXME */
00544   }
00545   for (code = 0; code < 256; code++) {
00546     if (!usedchars[code] ||
00547        !enc_vec[code]   || !strcmp(enc_vec[code], ".notdef"))
00548       continue;
00549     encoding->data.range1[encoding->num_entries].first  = code;
00550     encoding->data.range1[encoding->num_entries].n_left = 0;
00551     code++;
00552     while (code < 256 && usedchars[code] &&
00553           enc_vec[code] && strcmp(enc_vec[code], ".notdef")) {
00554       encoding->data.range1[encoding->num_entries].n_left += 1;
00555       code++;
00556     }
00557     encoding->num_entries += 1;
00558     /* The above while() loop stopped at unused char or code == 256. */
00559   }
00560   
00561   /* cleanup */
00562   if (encoding_id < 0 && enc_vec) {
00563     for (code = 0; code < 256; code++) {
00564       if (enc_vec[code]) {
00565        RELEASE(enc_vec[code]);
00566       }
00567     }
00568     RELEASE(enc_vec);
00569   }
00570 
00571   cff_release_index(cs_idx);
00572 
00573   charstrings->offset[num_glyphs] = charstring_len + 1;
00574   charstrings->count = num_glyphs;
00575   charstring_len     = cff_index_size(charstrings);
00576   cffont->num_glyphs = num_glyphs;
00577 
00578   /*
00579    * Discard old one, set new data.
00580    */
00581   if (cffont->charsets)
00582     cff_release_charsets(cffont->charsets);
00583   cffont->charsets = charset;
00584   if (cffont->encoding)
00585     cff_release_encoding(cffont->encoding);
00586   cffont->encoding = encoding;
00587   /*
00588    * We don't use subroutines at all.
00589    */
00590   if (cffont->gsubr)
00591     cff_release_index(cffont->gsubr);
00592   cffont->gsubr = cff_new_index(0);
00593   if (cffont->subrs[0])
00594     cff_release_index(cffont->subrs[0]);
00595   cffont->subrs[0] = NULL;
00596 
00597   /*
00598    * Flag must be reset since cff_pack_encoding(charset) does not write
00599    * encoding(charset) if HAVE_STANDARD_ENCODING(CHARSET) is set. We are
00600    * re-encoding font.
00601    */
00602   cffont->flag = FONTTYPE_FONT;
00603 
00604   /*
00605    * FIXME:
00606    *  Update String INDEX to delete unused strings.
00607    */
00608   cff_dict_update(cffont->topdict, cffont);
00609   if (cffont->private[0])
00610     cff_dict_update(cffont->private[0], cffont);
00611   cff_update_string(cffont);
00612 
00613   /*
00614    * Calculate sizes of Top DICT and Private DICT.
00615    * All offset values in DICT are set to long (32-bit) integer
00616    * in cff_dict_pack(), those values are updated later.
00617    */
00618   topdict = cff_new_index(1);
00619 
00620   cff_dict_remove(cffont->topdict, "UniqueID");
00621   cff_dict_remove(cffont->topdict, "XUID");
00622 
00623   /*
00624    * Force existence of Encoding.
00625    */
00626   if (!cff_dict_known(cffont->topdict, "Encoding"))
00627     cff_dict_add(cffont->topdict, "Encoding", 1);
00628   topdict->offset[1] = cff_dict_pack(cffont->topdict,
00629                                  (card8 *) work_buffer,
00630                                  WORK_BUFFER_SIZE) + 1;
00631   private_size = 0;
00632   if (cffont->private[0]) {
00633     cff_dict_remove(cffont->private[0], "Subrs"); /* no Subrs */
00634     private_size = cff_dict_pack(cffont->private[0],
00635                              (card8 *) work_buffer, WORK_BUFFER_SIZE);
00636   }
00637 
00638   /*
00639    * Estimate total size of fontfile.
00640    */
00641   stream_data_len = 4; /* header size */
00642 
00643   stream_data_len += cff_set_name(cffont, fullname);
00644   RELEASE(fullname);
00645 
00646   stream_data_len += cff_index_size(topdict);
00647   stream_data_len += cff_index_size(cffont->string);
00648   stream_data_len += cff_index_size(cffont->gsubr);
00649 
00650   /* We are using format 1 for Encoding and format 0 for charset.
00651    * TODO: Should implement cff_xxx_size().
00652    */
00653   stream_data_len += 2 + (encoding->num_entries)*2 + 1 + (encoding->num_supps)*3;
00654   stream_data_len += 1 + (charset->num_entries)*2;
00655   stream_data_len += charstring_len;
00656   stream_data_len += private_size;
00657 
00658   /*
00659    * Now we create FontFile data.
00660    */
00661   stream_data_ptr = NEW(stream_data_len, card8);
00662 
00663   /*
00664    * Data Layout order as described in CFF spec., sec 2 "Data Layout".
00665    */
00666   offset = 0;
00667   /* Header */
00668   offset += cff_put_header(cffont, stream_data_ptr + offset, stream_data_len - offset);
00669   /* Name */
00670   offset += cff_pack_index(cffont->name, stream_data_ptr + offset, stream_data_len - offset);
00671   /* Top DICT */
00672   topdict_offset = offset;
00673   offset += cff_index_size(topdict);
00674   /* Strings */
00675   offset += cff_pack_index(cffont->string,
00676                         stream_data_ptr + offset, stream_data_len - offset);
00677   /* Global Subrs */
00678   offset += cff_pack_index(cffont->gsubr,
00679                         stream_data_ptr + offset, stream_data_len - offset);
00680   /* Encoding */
00681   cff_dict_set(cffont->topdict, "Encoding", 0, offset);
00682   offset += cff_pack_encoding(cffont,
00683                            stream_data_ptr + offset, stream_data_len - offset);
00684   /* charset */
00685   cff_dict_set(cffont->topdict, "charset", 0, offset);
00686   offset += cff_pack_charsets(cffont,
00687                            stream_data_ptr + offset, stream_data_len - offset);
00688   /* CharStrings */
00689   cff_dict_set(cffont->topdict, "CharStrings", 0, offset);
00690   offset += cff_pack_index(charstrings,
00691                         stream_data_ptr + offset, charstring_len);
00692   cff_release_index(charstrings);
00693   /* Private */
00694   cff_dict_set(cffont->topdict, "Private", 1, offset);
00695   if (cffont->private[0] && private_size > 0)
00696     private_size = cff_dict_pack(cffont->private[0],
00697                              stream_data_ptr + offset, private_size);
00698   cff_dict_set(cffont->topdict, "Private", 0, private_size);
00699   offset += private_size;
00700 
00701   /* Finally Top DICT */
00702   topdict->data = NEW(topdict->offset[1] - 1, card8);
00703   cff_dict_pack (cffont->topdict, topdict->data, topdict->offset[1] - 1);
00704   cff_pack_index(topdict,
00705                stream_data_ptr + topdict_offset, cff_index_size(topdict));
00706   cff_release_index(topdict);
00707 
00708   /* Copyright and Trademark Notice ommited. */
00709 
00710   /* Handle Widths in fontdict. */
00711   add_SimpleMetrics(font, cffont, widths, num_glyphs);
00712 
00713   /* Close font */
00714   cff_close (cffont);
00715   sfnt_close(sfont);
00716 
00717   DPXFCLOSE(fp);
00718 
00719   if (verbose > 1) {
00720     MESG("[%u/%u glyphs][%ld bytes]", num_glyphs, cs_count, offset);
00721   }
00722 
00723   /*
00724    * CharSet might be recommended for subsetted font, but it is meaningful
00725    * only for Type 1 font...
00726    */
00727 
00728   /*
00729    * Write PDF FontFile data.
00730    */
00731   fontfile    = pdf_new_stream(STREAM_COMPRESS);
00732   stream_dict = pdf_stream_dict(fontfile);
00733   pdf_add_dict(descriptor,
00734               pdf_new_name("FontFile3"), pdf_ref_obj (fontfile));
00735   pdf_add_dict(stream_dict,
00736               pdf_new_name("Subtype"),   pdf_new_name("Type1C"));
00737   pdf_add_stream (fontfile, (void *) stream_data_ptr, offset);
00738   pdf_release_obj(fontfile);
00739 
00740   RELEASE(stream_data_ptr);
00741 
00742   return 0;
00743 }