Back to index

texmacs  1.0.7.15
Functions
type1.h File Reference
#include "pdffont.h"
This graph shows which files directly or indirectly include this file:

Go to the source code of this file.

Functions

int pdf_font_open_type1 (pdf_font *font)
int pdf_font_load_type1 (pdf_font *font)

Function Documentation

int pdf_font_load_type1 ( pdf_font font)

Definition at line 498 of file type1.c.

{
  pdf_obj      *fontdict, *descriptor;
  int           encoding_id;
  char         *usedchars, *ident;
  char         *fontname, *uniqueTag, *fontfile;
  char         *fullname; /* With pseudo unique tag */
  cff_font     *cffont;
  cff_charsets *charset;
  char        **enc_vec;
  double        defaultwidth, nominalwidth;
  double       *widths;
  card16       *GIDMap, num_glyphs = 0;
  FILE         *fp;
  long          offset;
  int           code, verbose;

  ASSERT(font);

  if (!pdf_font_is_in_use(font)) {
    return 0;
  }

  verbose     = pdf_font_get_verbose();

  encoding_id = pdf_font_get_encoding  (font);
  fontdict    = pdf_font_get_resource  (font);

  descriptor  = pdf_font_get_descriptor(font);
  usedchars   = pdf_font_get_usedchars (font);
  ident       = pdf_font_get_ident     (font);
  fontname    = pdf_font_get_fontname  (font);
  fontfile    = pdf_font_get_fontfile  (font);
  uniqueTag   = pdf_font_get_uniqueTag (font);
  if (!usedchars || !ident || !fontname) {
    ERROR("Type1: Unexpected error.");
  }

  
  if (fontfile)
    fp = MFOPEN(fontfile, FOPEN_RBIN_MODE);
  else
    fp = DPXFOPEN(ident, DPX_RES_TYPE_T1FONT);
  
  if (!fp) {
    ERROR("Type1: Could not open Type1 font: %s", ident);
  }

  GIDMap     = NULL;
  num_glyphs = 0;

  if (encoding_id >= 0) {
    enc_vec = NULL;
  } else {
    enc_vec = NEW(256, char *);
    for (code = 0; code <= 0xff; code++) {
      enc_vec[code] = NULL;
    }
  }

  cffont = t1_load_font(enc_vec, 0, fp);
  if (!cffont) {
    ERROR("Could not load Type 1 font: %s", ident);
  }
  DPXFCLOSE(fp);

  fullname = NEW(strlen(fontname) + 8, char);
  sprintf(fullname, "%6s+%s", uniqueTag, fontname);

  /*
   * Encoding related things.
   */
  if (encoding_id >= 0) {
    enc_vec = pdf_encoding_get_encoding(encoding_id);
  } else {
    pdf_obj *tounicode;

    /*
     * Create enc_vec and ToUnicode CMap for built-in encoding.
     */
    if (!pdf_lookup_dict(fontdict, "ToUnicode")) {
    tounicode = pdf_create_ToUnicode_CMap(fullname,
                                     enc_vec, usedchars);
    if (tounicode) {
      pdf_add_dict(fontdict,
                     pdf_new_name("ToUnicode"),
                     pdf_ref_obj (tounicode));
      pdf_release_obj(tounicode);
      }
    }
  }

  cff_set_name(cffont, fullname);
  RELEASE(fullname);

  /* defaultWidthX, CapHeight, etc. */
  get_font_attr(font, cffont);
  if (cff_dict_known(cffont->private[0], "defaultWidthX")) {
    defaultwidth = cff_dict_get(cffont->private[0], "defaultWidthX", 0);
  } else {
    defaultwidth = 0.0;
  }
  if (cff_dict_known(cffont->private[0], "nominalWidthX")) {
    nominalwidth = cff_dict_get(cffont->private[0], "nominalWidthX", 0);
  } else {
    nominalwidth = 0.0;
  }

  /* Create CFF encoding, charset, sort glyphs */
#define MAX_GLYPHS 1024
  GIDMap = NEW(MAX_GLYPHS, card16);
  {
    int     prev, duplicate;
    long    gid;
    char   *glyph;
    s_SID   sid;

    cffont->encoding = NEW(1, cff_encoding);
    cffont->encoding->format      = 1;
    cffont->encoding->num_entries = 0;
    cffont->encoding->data.range1 = NEW(256, cff_range1);
    cffont->encoding->num_supps   = 0;
    cffont->encoding->supp        = NEW(256, cff_map);

    charset = NEW(1, cff_charsets);
    charset->format      = 0;
    charset->num_entries = 0;
    charset->data.glyphs = NEW(MAX_GLYPHS, s_SID);

    gid = cff_glyph_lookup(cffont, ".notdef");
    if (gid < 0)
      ERROR("Type 1 font with no \".notdef\" glyph???");
    GIDMap[0] = (card16) gid;
    if (verbose > 2)
      MESG("[glyphs:/.notdef");
    num_glyphs =  1;
    for (prev = -2, code = 0; code <= 0xff; code++) {
      glyph = enc_vec[code];

      if (!usedchars[code])
       continue;
      if (glyph && !strcmp(glyph, ".notdef")) {
       WARN("Character mapped to .notdef used in font: %s",
            fontname);
       usedchars[code] = 0;
       continue;
      }

      gid = cff_glyph_lookup(cffont, glyph);
      if (gid < 1 || gid >= cffont->cstrings->count) {
       WARN("Glyph \"%s\" missing in font \"%s\".", glyph, fontname);
       usedchars[code] = 0;
       continue;
      }

      for (duplicate = 0; duplicate < code; duplicate++) {
       if (usedchars[duplicate] &&
           enc_vec[duplicate]   && !strcmp(enc_vec[duplicate], glyph))
         break;
      }

      sid = cff_add_string(cffont, glyph, 1); /* FIXME */
      if (duplicate < code) { /* found duplicates */
       cffont->encoding->supp[cffont->encoding->num_supps].code  = duplicate;
       cffont->encoding->supp[cffont->encoding->num_supps].glyph = sid;
       cffont->encoding->num_supps += 1;
      } else {
       GIDMap[num_glyphs] = (card16) gid;
       charset->data.glyphs[charset->num_entries] = sid;
       charset->num_entries += 1;
       if (code != prev + 1) {
         cffont->encoding->num_entries += 1;
         cffont->encoding->data.range1[cffont->encoding->num_entries-1].first  = code;
         cffont->encoding->data.range1[cffont->encoding->num_entries-1].n_left = 0;
       } else {
         cffont->encoding->data.range1[cffont->encoding->num_entries-1].n_left += 1;
       }
       prev = code;
       num_glyphs++;

       if (verbose > 2) {
         MESG("/%s", glyph);
       }

      }
    }
    if (cffont->encoding->num_supps > 0) {
      cffont->encoding->format |= 0x80;
    } else {
      RELEASE(cffont->encoding->supp); /* FIXME */
      cffont->encoding->supp = NULL;
    }
  }

  widths = NEW(cffont->cstrings->count, double);
  /*
   * No more string will be added.
   * The Type 1 seac operator may add another glyph but the glyph name of
   * those glyphs are contained in standard string. The String Index will
   * not be modified after here.
   * BUT: We cannot update the String Index yet because then we wouldn't be
   * able to find the GIDs of the base and accent characters (unless they
   * have been used already).
   */

  {
    cff_index *cstring;
    t1_ginfo   gm;
    card16     gid, gid_orig;
    long       dstlen_max, srclen;
    int        have_seac = 0;
    card8     *srcptr, *dstptr;

    offset  = dstlen_max = 0L;
    cstring = cff_new_index(cffont->cstrings->count);
    cstring->data      = NULL;
    cstring->offset[0] = 1;
    
    /* The num_glyphs increases if "seac" operators are used. */
    for (gid = 0; gid < num_glyphs; gid++) {
      if (offset + CS_STR_LEN_MAX >= dstlen_max) {
       dstlen_max += CS_STR_LEN_MAX * 2;
       cstring->data = RENEW(cstring->data, dstlen_max, card8);
      }
      gid_orig = GIDMap[gid];

      dstptr   = cstring->data + cstring->offset[gid] - 1;
      srcptr   = cffont->cstrings->data + cffont->cstrings->offset[gid_orig] - 1;
      srclen   = cffont->cstrings->offset[gid_orig + 1] - cffont->cstrings->offset[gid_orig];

      offset  += t1char_convert_charstring(dstptr, CS_STR_LEN_MAX,
                                      srcptr, srclen,
                                      cffont->subrs[0], defaultwidth, nominalwidth, &gm);
      cstring->offset[gid + 1] = offset + 1;
      if (gm.use_seac) {
       long  bchar_gid, achar_gid, i;
       char *bchar_name, *achar_name;

       /*
        * NOTE:
        *  1. seac.achar and seac.bchar must be contained in the CFF standard string.
        *  2. Those characters need not to be encoded.
        *  3. num_glyphs == charsets->num_entries + 1.
        */
       achar_name = t1_get_standard_glyph(gm.seac.achar);
       achar_gid  = cff_glyph_lookup(cffont, achar_name);
       bchar_name = t1_get_standard_glyph(gm.seac.bchar);
       bchar_gid  = cff_glyph_lookup(cffont, bchar_name);
       if (achar_gid < 0) {
         WARN("Accent char \"%s\" not found. Invalid use of \"seac\" operator.",
              achar_name);
         continue;
       }
       if (bchar_gid < 0) {
         WARN("Base char \"%s\" not found. Invalid use of \"seac\" operator.",
              bchar_name);
         continue;
       }

       for (i = 0; i < num_glyphs; i++) {
         if (GIDMap[i] == achar_gid)
           break;
       }
       if (i == num_glyphs) {
         if (verbose > 2)
           MESG("/%s", achar_name);
         GIDMap[num_glyphs++] = achar_gid;
         charset->data.glyphs[charset->num_entries] = cff_get_sid(cffont, achar_name);
         charset->num_entries += 1;
       }

       for (i = 0; i < num_glyphs; i++) {
         if (GIDMap[i] == bchar_gid)
           break;
       }
       if (i == num_glyphs) {
         if (verbose > 2)
           MESG("/%s", bchar_name);
         GIDMap[num_glyphs++] = bchar_gid;
         charset->data.glyphs[charset->num_entries] = cff_get_sid(cffont, bchar_name);
         charset->num_entries += 1;
       }
       have_seac = 1;
      }
      widths[gid] = gm.wx;
    }
    cstring->count = num_glyphs;

    cff_release_index(cffont->subrs[0]);
    cffont->subrs[0] = NULL;
    RELEASE(cffont->subrs);
    cffont->subrs    = NULL;

    cff_release_index(cffont->cstrings);
    cffont->cstrings = cstring;

    cff_release_charsets(cffont->charsets);
    cffont->charsets = charset;
  }
  if (verbose > 2)
    MESG("]");

  /* Now we can update the String Index */
  cff_dict_update  (cffont->topdict,    cffont);
  cff_dict_update  (cffont->private[0], cffont);
  cff_update_string(cffont);

  add_metrics(font, cffont, enc_vec, widths, num_glyphs);

  offset = write_fontfile(font, cffont, num_glyphs);
  if (verbose > 1)
    MESG("[%u glyphs][%ld bytes]", num_glyphs, offset);

  cff_close(cffont);

  /* Cleanup */
  if (encoding_id < 0 && enc_vec) {
    for (code = 0; code < 256; code++) {
      if (enc_vec[code])
       RELEASE(enc_vec[code]);
      enc_vec[code] = NULL;
    }
    RELEASE(enc_vec);
  }
  if (widths)
    RELEASE(widths);
  if (GIDMap)
    RELEASE(GIDMap);

  /*
   * Maybe writing Charset is recommended for subsetted font.
   */

  return 0;
}

Here is the call graph for this function:

Here is the caller graph for this function:

int pdf_font_open_type1 ( pdf_font font)

Definition at line 94 of file type1.c.

{
  char    *ident;
  FILE    *fp;
  char     fontname[PDF_NAME_LEN_MAX+1];

  ASSERT(font);

  ident = pdf_font_get_ident(font);

  if (is_basefont(ident)) {
    pdf_font_set_fontname(font, ident);
    pdf_font_set_subtype (font, PDF_FONT_FONTTYPE_TYPE1);
    pdf_font_set_flags   (font,
                       (PDF_FONT_FLAG_NOEMBED|PDF_FONT_FLAG_BASEFONT));
  } else {
    {
      char *fontfile =   pdf_font_get_fontfile  (font);

      if (fontfile) {
        fp = MFOPEN(fontfile, FOPEN_RBIN_MODE);
        if (fp && !is_pfb(fp)) {
          DPXFCLOSE(fp);
          fp = NULL;
        }
      }
      else
        fp = DPXFOPEN(ident, DPX_RES_TYPE_T1FONT);
    }
    if (!fp)
      return -1;

    memset(fontname, 0, PDF_NAME_LEN_MAX+1);
    if (!is_pfb(fp) || t1_get_fontname(fp, fontname) < 0) {
      ERROR("Failed to read Type 1 font \"%s\".", ident);
    }
    DPXFCLOSE(fp);

    pdf_font_set_fontname(font, fontname);
    pdf_font_set_subtype (font, PDF_FONT_FONTTYPE_TYPE1);
  }

  return 0;
}

Here is the call graph for this function:

Here is the caller graph for this function: